blob: 03a3e5c65ee78c53c017096ca55cf35d81ec0402 [file] [log] [blame]
Manjunath Hadli606b69e2011-06-17 04:01:34 -03001/*
2 * Copyright (C) 2010 Texas Instruments Inc
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation version 2.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
17#include <linux/module.h>
18#include <linux/kernel.h>
19#include <linux/init.h>
20#include <linux/ctype.h>
21#include <linux/delay.h>
22#include <linux/device.h>
23#include <linux/interrupt.h>
24#include <linux/platform_device.h>
25#include <linux/videodev2.h>
26#include <linux/slab.h>
27
28#include <mach/hardware.h>
29#include <mach/mux.h>
30#include <mach/io.h>
31#include <mach/i2c.h>
32
33#include <linux/io.h>
34
35#include <media/davinci/vpbe_types.h>
36#include <media/davinci/vpbe_venc.h>
37#include <media/davinci/vpss.h>
38#include <media/v4l2-device.h>
39
40#include "vpbe_venc_regs.h"
41
42#define MODULE_NAME VPBE_VENC_SUBDEV_NAME
43
44static int debug = 2;
45module_param(debug, int, 0644);
46MODULE_PARM_DESC(debug, "Debug level 0-2");
47
48struct venc_state {
49 struct v4l2_subdev sd;
50 struct venc_callback *callback;
51 struct venc_platform_data *pdata;
52 struct device *pdev;
53 u32 output;
54 v4l2_std_id std;
55 spinlock_t lock;
56 void __iomem *venc_base;
57 void __iomem *vdaccfg_reg;
58};
59
60static inline struct venc_state *to_state(struct v4l2_subdev *sd)
61{
62 return container_of(sd, struct venc_state, sd);
63}
64
65static inline u32 venc_read(struct v4l2_subdev *sd, u32 offset)
66{
67 struct venc_state *venc = to_state(sd);
68
69 return readl(venc->venc_base + offset);
70}
71
72static inline u32 venc_write(struct v4l2_subdev *sd, u32 offset, u32 val)
73{
74 struct venc_state *venc = to_state(sd);
75
76 writel(val, (venc->venc_base + offset));
77
78 return val;
79}
80
81static inline u32 venc_modify(struct v4l2_subdev *sd, u32 offset,
82 u32 val, u32 mask)
83{
84 u32 new_val = (venc_read(sd, offset) & ~mask) | (val & mask);
85
86 venc_write(sd, offset, new_val);
87
88 return new_val;
89}
90
91static inline u32 vdaccfg_write(struct v4l2_subdev *sd, u32 val)
92{
93 struct venc_state *venc = to_state(sd);
94
95 writel(val, venc->vdaccfg_reg);
96
97 val = readl(venc->vdaccfg_reg);
98
99 return val;
100}
101
102/* This function sets the dac of the VPBE for various outputs
103 */
104static int venc_set_dac(struct v4l2_subdev *sd, u32 out_index)
105{
106 switch (out_index) {
107 case 0:
108 v4l2_dbg(debug, 1, sd, "Setting output to Composite\n");
109 venc_write(sd, VENC_DACSEL, 0);
110 break;
111 case 1:
112 v4l2_dbg(debug, 1, sd, "Setting output to S-Video\n");
113 venc_write(sd, VENC_DACSEL, 0x210);
114 break;
115 case 2:
116 venc_write(sd, VENC_DACSEL, 0x543);
117 break;
118 default:
119 return -EINVAL;
120 }
121
122 return 0;
123}
124
125static void venc_enabledigitaloutput(struct v4l2_subdev *sd, int benable)
126{
127 v4l2_dbg(debug, 2, sd, "venc_enabledigitaloutput\n");
128
129 if (benable) {
130 venc_write(sd, VENC_VMOD, 0);
131 venc_write(sd, VENC_CVBS, 0);
132 venc_write(sd, VENC_LCDOUT, 0);
133 venc_write(sd, VENC_HSPLS, 0);
134 venc_write(sd, VENC_HSTART, 0);
135 venc_write(sd, VENC_HVALID, 0);
136 venc_write(sd, VENC_HINT, 0);
137 venc_write(sd, VENC_VSPLS, 0);
138 venc_write(sd, VENC_VSTART, 0);
139 venc_write(sd, VENC_VVALID, 0);
140 venc_write(sd, VENC_VINT, 0);
141 venc_write(sd, VENC_YCCCTL, 0);
142 venc_write(sd, VENC_DACSEL, 0);
143
144 } else {
145 venc_write(sd, VENC_VMOD, 0);
146 /* disable VCLK output pin enable */
147 venc_write(sd, VENC_VIDCTL, 0x141);
148
149 /* Disable output sync pins */
150 venc_write(sd, VENC_SYNCCTL, 0);
151
152 /* Disable DCLOCK */
153 venc_write(sd, VENC_DCLKCTL, 0);
154 venc_write(sd, VENC_DRGBX1, 0x0000057C);
155
156 /* Disable LCD output control (accepting default polarity) */
157 venc_write(sd, VENC_LCDOUT, 0);
158 venc_write(sd, VENC_CMPNT, 0x100);
159 venc_write(sd, VENC_HSPLS, 0);
160 venc_write(sd, VENC_HINT, 0);
161 venc_write(sd, VENC_HSTART, 0);
162 venc_write(sd, VENC_HVALID, 0);
163
164 venc_write(sd, VENC_VSPLS, 0);
165 venc_write(sd, VENC_VINT, 0);
166 venc_write(sd, VENC_VSTART, 0);
167 venc_write(sd, VENC_VVALID, 0);
168
169 venc_write(sd, VENC_HSDLY, 0);
170 venc_write(sd, VENC_VSDLY, 0);
171
172 venc_write(sd, VENC_YCCCTL, 0);
173 venc_write(sd, VENC_VSTARTA, 0);
174
175 /* Set OSD clock and OSD Sync Adavance registers */
176 venc_write(sd, VENC_OSDCLK0, 1);
177 venc_write(sd, VENC_OSDCLK1, 2);
178 }
179}
180
181/*
182 * setting NTSC mode
183 */
184static int venc_set_ntsc(struct v4l2_subdev *sd)
185{
186 struct venc_state *venc = to_state(sd);
187 struct venc_platform_data *pdata = venc->pdata;
188
189 v4l2_dbg(debug, 2, sd, "venc_set_ntsc\n");
190
191 /* Setup clock at VPSS & VENC for SD */
192 vpss_enable_clock(VPSS_VENC_CLOCK_SEL, 1);
193 if (pdata->setup_clock(VPBE_ENC_STD, V4L2_STD_525_60) < 0)
194 return -EINVAL;
195
196 venc_enabledigitaloutput(sd, 0);
197
198 /* to set VENC CLK DIV to 1 - final clock is 54 MHz */
199 venc_modify(sd, VENC_VIDCTL, 0, 1 << 1);
200 /* Set REC656 Mode */
201 venc_write(sd, VENC_YCCCTL, 0x1);
202 venc_modify(sd, VENC_VDPRO, 0, VENC_VDPRO_DAFRQ);
203 venc_modify(sd, VENC_VDPRO, 0, VENC_VDPRO_DAUPS);
204
205 venc_write(sd, VENC_VMOD, 0);
206 venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
207 VENC_VMOD_VIE);
208 venc_modify(sd, VENC_VMOD, (0 << VENC_VMOD_VMD), VENC_VMOD_VMD);
209 venc_modify(sd, VENC_VMOD, (0 << VENC_VMOD_TVTYP_SHIFT),
210 VENC_VMOD_TVTYP);
211 venc_write(sd, VENC_DACTST, 0x0);
212 venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
213
214 return 0;
215}
216
217/*
218 * setting PAL mode
219 */
220static int venc_set_pal(struct v4l2_subdev *sd)
221{
222 struct venc_state *venc = to_state(sd);
223
224 v4l2_dbg(debug, 2, sd, "venc_set_pal\n");
225
226 /* Setup clock at VPSS & VENC for SD */
227 vpss_enable_clock(VPSS_VENC_CLOCK_SEL, 1);
228 if (venc->pdata->setup_clock(VPBE_ENC_STD, V4L2_STD_625_50) < 0)
229 return -EINVAL;
230
231 venc_enabledigitaloutput(sd, 0);
232
233 /* to set VENC CLK DIV to 1 - final clock is 54 MHz */
234 venc_modify(sd, VENC_VIDCTL, 0, 1 << 1);
235 /* Set REC656 Mode */
236 venc_write(sd, VENC_YCCCTL, 0x1);
237
238 venc_modify(sd, VENC_SYNCCTL, 1 << VENC_SYNCCTL_OVD_SHIFT,
239 VENC_SYNCCTL_OVD);
240 venc_write(sd, VENC_VMOD, 0);
241 venc_modify(sd, VENC_VMOD,
242 (1 << VENC_VMOD_VIE_SHIFT),
243 VENC_VMOD_VIE);
244 venc_modify(sd, VENC_VMOD,
245 (0 << VENC_VMOD_VMD), VENC_VMOD_VMD);
246 venc_modify(sd, VENC_VMOD,
247 (1 << VENC_VMOD_TVTYP_SHIFT),
248 VENC_VMOD_TVTYP);
249 venc_write(sd, VENC_DACTST, 0x0);
250 venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
251
252 return 0;
253}
254
255/*
256 * venc_set_480p59_94
257 *
258 * This function configures the video encoder to EDTV(525p) component setting.
259 */
260static int venc_set_480p59_94(struct v4l2_subdev *sd)
261{
262 struct venc_state *venc = to_state(sd);
263 struct venc_platform_data *pdata = venc->pdata;
264
265 v4l2_dbg(debug, 2, sd, "venc_set_480p59_94\n");
266
267 /* Setup clock at VPSS & VENC for SD */
268 if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_480P59_94) < 0)
269 return -EINVAL;
270
271 venc_enabledigitaloutput(sd, 0);
272
273 venc_write(sd, VENC_OSDCLK0, 0);
274 venc_write(sd, VENC_OSDCLK1, 1);
275 venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ,
276 VENC_VDPRO_DAFRQ);
277 venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS,
278 VENC_VDPRO_DAUPS);
279 venc_write(sd, VENC_VMOD, 0);
280 venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
281 VENC_VMOD_VIE);
282 venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD);
283 venc_modify(sd, VENC_VMOD, (HDTV_525P << VENC_VMOD_TVTYP_SHIFT),
284 VENC_VMOD_TVTYP);
285 venc_modify(sd, VENC_VMOD, VENC_VMOD_VDMD_YCBCR8 <<
286 VENC_VMOD_VDMD_SHIFT, VENC_VMOD_VDMD);
287
288 venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
289
290 return 0;
291}
292
293/*
294 * venc_set_625p
295 *
296 * This function configures the video encoder to HDTV(625p) component setting
297 */
298static int venc_set_576p50(struct v4l2_subdev *sd)
299{
300 struct venc_state *venc = to_state(sd);
301 struct venc_platform_data *pdata = venc->pdata;
302
303 v4l2_dbg(debug, 2, sd, "venc_set_576p50\n");
304
305 /* Setup clock at VPSS & VENC for SD */
306 if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_576P50) < 0)
307 return -EINVAL;
308
309 venc_enabledigitaloutput(sd, 0);
310
311 venc_write(sd, VENC_OSDCLK0, 0);
312 venc_write(sd, VENC_OSDCLK1, 1);
313
314 venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ,
315 VENC_VDPRO_DAFRQ);
316 venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS,
317 VENC_VDPRO_DAUPS);
318
319 venc_write(sd, VENC_VMOD, 0);
320 venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
321 VENC_VMOD_VIE);
322 venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD);
323 venc_modify(sd, VENC_VMOD, (HDTV_625P << VENC_VMOD_TVTYP_SHIFT),
324 VENC_VMOD_TVTYP);
325
326 venc_modify(sd, VENC_VMOD, VENC_VMOD_VDMD_YCBCR8 <<
327 VENC_VMOD_VDMD_SHIFT, VENC_VMOD_VDMD);
328 venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
329
330 return 0;
331}
332
333static int venc_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm)
334{
335 v4l2_dbg(debug, 1, sd, "venc_s_std_output\n");
336
337 if (norm & V4L2_STD_525_60)
338 return venc_set_ntsc(sd);
339 else if (norm & V4L2_STD_625_50)
340 return venc_set_pal(sd);
341
342 return -EINVAL;
343}
344
345static int venc_s_dv_preset(struct v4l2_subdev *sd,
346 struct v4l2_dv_preset *dv_preset)
347{
348 v4l2_dbg(debug, 1, sd, "venc_s_dv_preset\n");
349
350 if (dv_preset->preset == V4L2_DV_576P50)
351 return venc_set_576p50(sd);
352 else if (dv_preset->preset == V4L2_DV_480P59_94)
353 return venc_set_480p59_94(sd);
354
355 return -EINVAL;
356}
357
358static int venc_s_routing(struct v4l2_subdev *sd, u32 input, u32 output,
359 u32 config)
360{
361 struct venc_state *venc = to_state(sd);
362 int ret;
363
364 v4l2_dbg(debug, 1, sd, "venc_s_routing\n");
365
366 ret = venc_set_dac(sd, output);
367 if (!ret)
368 venc->output = output;
369
370 return ret;
371}
372
373static long venc_ioctl(struct v4l2_subdev *sd,
374 unsigned int cmd,
375 void *arg)
376{
377 u32 val;
378
379 switch (cmd) {
380 case VENC_GET_FLD:
381 val = venc_read(sd, VENC_VSTAT);
382 *((int *)arg) = ((val & VENC_VSTAT_FIDST) ==
383 VENC_VSTAT_FIDST);
384 break;
385 default:
386 v4l2_err(sd, "Wrong IOCTL cmd\n");
387 break;
388 }
389
390 return 0;
391}
392
393static const struct v4l2_subdev_core_ops venc_core_ops = {
394 .ioctl = venc_ioctl,
395};
396
397static const struct v4l2_subdev_video_ops venc_video_ops = {
398 .s_routing = venc_s_routing,
399 .s_std_output = venc_s_std_output,
400 .s_dv_preset = venc_s_dv_preset,
401};
402
403static const struct v4l2_subdev_ops venc_ops = {
404 .core = &venc_core_ops,
405 .video = &venc_video_ops,
406};
407
408static int venc_initialize(struct v4l2_subdev *sd)
409{
410 struct venc_state *venc = to_state(sd);
411 int ret;
412
413 /* Set default to output to composite and std to NTSC */
414 venc->output = 0;
415 venc->std = V4L2_STD_525_60;
416
417 ret = venc_s_routing(sd, 0, venc->output, 0);
418 if (ret < 0) {
419 v4l2_err(sd, "Error setting output during init\n");
420 return -EINVAL;
421 }
422
423 ret = venc_s_std_output(sd, venc->std);
424 if (ret < 0) {
425 v4l2_err(sd, "Error setting std during init\n");
426 return -EINVAL;
427 }
428
429 return ret;
430}
431
432static int venc_device_get(struct device *dev, void *data)
433{
434 struct platform_device *pdev = to_platform_device(dev);
435 struct venc_state **venc = data;
436
437 if (strcmp(MODULE_NAME, pdev->name) == 0)
438 *venc = platform_get_drvdata(pdev);
439
440 return 0;
441}
442
443struct v4l2_subdev *venc_sub_dev_init(struct v4l2_device *v4l2_dev,
444 const char *venc_name)
445{
446 struct venc_state *venc;
447 int err;
448
449 err = bus_for_each_dev(&platform_bus_type, NULL, &venc,
450 venc_device_get);
451 if (venc == NULL)
452 return NULL;
453
454 v4l2_subdev_init(&venc->sd, &venc_ops);
455
456 strcpy(venc->sd.name, venc_name);
457 if (v4l2_device_register_subdev(v4l2_dev, &venc->sd) < 0) {
458 v4l2_err(v4l2_dev,
459 "vpbe unable to register venc sub device\n");
460 return NULL;
461 }
462 if (venc_initialize(&venc->sd)) {
463 v4l2_err(v4l2_dev,
464 "vpbe venc initialization failed\n");
465 return NULL;
466 }
467
468 return &venc->sd;
469}
470EXPORT_SYMBOL(venc_sub_dev_init);
471
472static int venc_probe(struct platform_device *pdev)
473{
474 struct venc_state *venc;
475 struct resource *res;
476 int ret;
477
478 venc = kzalloc(sizeof(struct venc_state), GFP_KERNEL);
479 if (venc == NULL)
480 return -ENOMEM;
481
482 venc->pdev = &pdev->dev;
483 venc->pdata = pdev->dev.platform_data;
484 if (NULL == venc->pdata) {
485 dev_err(venc->pdev, "Unable to get platform data for"
486 " VENC sub device");
487 ret = -ENOENT;
488 goto free_mem;
489 }
490 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
491 if (!res) {
492 dev_err(venc->pdev,
493 "Unable to get VENC register address map\n");
494 ret = -ENODEV;
495 goto free_mem;
496 }
497
498 if (!request_mem_region(res->start, resource_size(res), "venc")) {
499 dev_err(venc->pdev, "Unable to reserve VENC MMIO region\n");
500 ret = -ENODEV;
501 goto free_mem;
502 }
503
504 venc->venc_base = ioremap_nocache(res->start, resource_size(res));
505 if (!venc->venc_base) {
506 dev_err(venc->pdev, "Unable to map VENC IO space\n");
507 ret = -ENODEV;
508 goto release_venc_mem_region;
509 }
510
511 spin_lock_init(&venc->lock);
512 platform_set_drvdata(pdev, venc);
513 dev_notice(venc->pdev, "VENC sub device probe success\n");
514 return 0;
515
516release_venc_mem_region:
517 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
518 release_mem_region(res->start, resource_size(res));
519free_mem:
520 kfree(venc);
521 return ret;
522}
523
524static int venc_remove(struct platform_device *pdev)
525{
526 struct venc_state *venc = platform_get_drvdata(pdev);
527 struct resource *res;
528
529 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
530 iounmap((void *)venc->venc_base);
531 release_mem_region(res->start, resource_size(res));
532 kfree(venc);
533
534 return 0;
535}
536
537static struct platform_driver venc_driver = {
538 .probe = venc_probe,
539 .remove = venc_remove,
540 .driver = {
541 .name = MODULE_NAME,
542 .owner = THIS_MODULE,
543 },
544};
545
546static int venc_init(void)
547{
548 if (platform_driver_register(&venc_driver)) {
549 printk(KERN_ERR "Unable to register venc driver\n");
550 return -ENODEV;
551 }
552 return 0;
553}
554
555static void venc_exit(void)
556{
557 platform_driver_unregister(&venc_driver);
558 return;
559}
560
561module_init(venc_init);
562module_exit(venc_exit);
563
564MODULE_LICENSE("GPL");
565MODULE_DESCRIPTION("VPBE VENC Driver");
566MODULE_AUTHOR("Texas Instruments");