treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 286
[sfrench/cifs-2.6.git] / drivers / media / platform / davinci / vpbe_venc.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2010 Texas Instruments Inc
4  */
5 #include <linux/module.h>
6 #include <linux/mod_devicetable.h>
7 #include <linux/kernel.h>
8 #include <linux/init.h>
9 #include <linux/ctype.h>
10 #include <linux/delay.h>
11 #include <linux/device.h>
12 #include <linux/interrupt.h>
13 #include <linux/platform_device.h>
14 #include <linux/videodev2.h>
15 #include <linux/slab.h>
16
17 #ifdef CONFIG_ARCH_DAVINCI
18 #include <mach/hardware.h>
19 #include <mach/mux.h>
20 #endif
21
22 #include <linux/platform_data/i2c-davinci.h>
23
24 #include <linux/io.h>
25
26 #include <media/davinci/vpbe_types.h>
27 #include <media/davinci/vpbe_venc.h>
28 #include <media/davinci/vpss.h>
29 #include <media/v4l2-device.h>
30
31 #include "vpbe_venc_regs.h"
32
33 #define MODULE_NAME     "davinci-vpbe-venc"
34
35 static const struct platform_device_id vpbe_venc_devtype[] = {
36         {
37                 .name = DM644X_VPBE_VENC_SUBDEV_NAME,
38                 .driver_data = VPBE_VERSION_1,
39         }, {
40                 .name = DM365_VPBE_VENC_SUBDEV_NAME,
41                 .driver_data = VPBE_VERSION_2,
42         }, {
43                 .name = DM355_VPBE_VENC_SUBDEV_NAME,
44                 .driver_data = VPBE_VERSION_3,
45         },
46         {
47                 /* sentinel */
48         }
49 };
50
51 MODULE_DEVICE_TABLE(platform, vpbe_venc_devtype);
52
53 static int debug = 2;
54 module_param(debug, int, 0644);
55 MODULE_PARM_DESC(debug, "Debug level 0-2");
56
57 struct venc_state {
58         struct v4l2_subdev sd;
59         struct venc_callback *callback;
60         struct venc_platform_data *pdata;
61         struct device *pdev;
62         u32 output;
63         v4l2_std_id std;
64         spinlock_t lock;
65         void __iomem *venc_base;
66         void __iomem *vdaccfg_reg;
67         enum vpbe_version venc_type;
68 };
69
70 static inline struct venc_state *to_state(struct v4l2_subdev *sd)
71 {
72         return container_of(sd, struct venc_state, sd);
73 }
74
75 static inline u32 venc_read(struct v4l2_subdev *sd, u32 offset)
76 {
77         struct venc_state *venc = to_state(sd);
78
79         return readl(venc->venc_base + offset);
80 }
81
82 static inline u32 venc_write(struct v4l2_subdev *sd, u32 offset, u32 val)
83 {
84         struct venc_state *venc = to_state(sd);
85
86         writel(val, (venc->venc_base + offset));
87
88         return val;
89 }
90
91 static inline u32 venc_modify(struct v4l2_subdev *sd, u32 offset,
92                                  u32 val, u32 mask)
93 {
94         u32 new_val = (venc_read(sd, offset) & ~mask) | (val & mask);
95
96         venc_write(sd, offset, new_val);
97
98         return new_val;
99 }
100
101 static inline u32 vdaccfg_write(struct v4l2_subdev *sd, u32 val)
102 {
103         struct venc_state *venc = to_state(sd);
104
105         writel(val, venc->vdaccfg_reg);
106
107         val = readl(venc->vdaccfg_reg);
108
109         return val;
110 }
111
112 #define VDAC_COMPONENT  0x543
113 #define VDAC_S_VIDEO    0x210
114 /* This function sets the dac of the VPBE for various outputs
115  */
116 static int venc_set_dac(struct v4l2_subdev *sd, u32 out_index)
117 {
118         switch (out_index) {
119         case 0:
120                 v4l2_dbg(debug, 1, sd, "Setting output to Composite\n");
121                 venc_write(sd, VENC_DACSEL, 0);
122                 break;
123         case 1:
124                 v4l2_dbg(debug, 1, sd, "Setting output to Component\n");
125                 venc_write(sd, VENC_DACSEL, VDAC_COMPONENT);
126                 break;
127         case 2:
128                 v4l2_dbg(debug, 1, sd, "Setting output to S-video\n");
129                 venc_write(sd, VENC_DACSEL, VDAC_S_VIDEO);
130                 break;
131         default:
132                 return -EINVAL;
133         }
134
135         return 0;
136 }
137
138 static void venc_enabledigitaloutput(struct v4l2_subdev *sd, int benable)
139 {
140         struct venc_state *venc = to_state(sd);
141
142         v4l2_dbg(debug, 2, sd, "venc_enabledigitaloutput\n");
143
144         if (benable) {
145                 venc_write(sd, VENC_VMOD, 0);
146                 venc_write(sd, VENC_CVBS, 0);
147                 venc_write(sd, VENC_LCDOUT, 0);
148                 venc_write(sd, VENC_HSPLS, 0);
149                 venc_write(sd, VENC_HSTART, 0);
150                 venc_write(sd, VENC_HVALID, 0);
151                 venc_write(sd, VENC_HINT, 0);
152                 venc_write(sd, VENC_VSPLS, 0);
153                 venc_write(sd, VENC_VSTART, 0);
154                 venc_write(sd, VENC_VVALID, 0);
155                 venc_write(sd, VENC_VINT, 0);
156                 venc_write(sd, VENC_YCCCTL, 0);
157                 venc_write(sd, VENC_DACSEL, 0);
158
159         } else {
160                 venc_write(sd, VENC_VMOD, 0);
161                 /* disable VCLK output pin enable */
162                 venc_write(sd, VENC_VIDCTL, 0x141);
163
164                 /* Disable output sync pins */
165                 venc_write(sd, VENC_SYNCCTL, 0);
166
167                 /* Disable DCLOCK */
168                 venc_write(sd, VENC_DCLKCTL, 0);
169                 venc_write(sd, VENC_DRGBX1, 0x0000057C);
170
171                 /* Disable LCD output control (accepting default polarity) */
172                 venc_write(sd, VENC_LCDOUT, 0);
173                 if (venc->venc_type != VPBE_VERSION_3)
174                         venc_write(sd, VENC_CMPNT, 0x100);
175                 venc_write(sd, VENC_HSPLS, 0);
176                 venc_write(sd, VENC_HINT, 0);
177                 venc_write(sd, VENC_HSTART, 0);
178                 venc_write(sd, VENC_HVALID, 0);
179
180                 venc_write(sd, VENC_VSPLS, 0);
181                 venc_write(sd, VENC_VINT, 0);
182                 venc_write(sd, VENC_VSTART, 0);
183                 venc_write(sd, VENC_VVALID, 0);
184
185                 venc_write(sd, VENC_HSDLY, 0);
186                 venc_write(sd, VENC_VSDLY, 0);
187
188                 venc_write(sd, VENC_YCCCTL, 0);
189                 venc_write(sd, VENC_VSTARTA, 0);
190
191                 /* Set OSD clock and OSD Sync Adavance registers */
192                 venc_write(sd, VENC_OSDCLK0, 1);
193                 venc_write(sd, VENC_OSDCLK1, 2);
194         }
195 }
196
197 static void
198 venc_enable_vpss_clock(int venc_type,
199                        enum vpbe_enc_timings_type type,
200                        unsigned int pclock)
201 {
202         if (venc_type == VPBE_VERSION_1)
203                 return;
204
205         if (venc_type == VPBE_VERSION_2 && (type == VPBE_ENC_STD || (type ==
206             VPBE_ENC_DV_TIMINGS && pclock <= 27000000))) {
207                 vpss_enable_clock(VPSS_VENC_CLOCK_SEL, 1);
208                 vpss_enable_clock(VPSS_VPBE_CLOCK, 1);
209                 return;
210         }
211
212         if (venc_type == VPBE_VERSION_3 && type == VPBE_ENC_STD)
213                 vpss_enable_clock(VPSS_VENC_CLOCK_SEL, 0);
214 }
215
216 #define VDAC_CONFIG_SD_V3       0x0E21A6B6
217 #define VDAC_CONFIG_SD_V2       0x081141CF
218 /*
219  * setting NTSC mode
220  */
221 static int venc_set_ntsc(struct v4l2_subdev *sd)
222 {
223         struct venc_state *venc = to_state(sd);
224         struct venc_platform_data *pdata = venc->pdata;
225
226         v4l2_dbg(debug, 2, sd, "venc_set_ntsc\n");
227
228         /* Setup clock at VPSS & VENC for SD */
229         vpss_enable_clock(VPSS_VENC_CLOCK_SEL, 1);
230         if (pdata->setup_clock(VPBE_ENC_STD, V4L2_STD_525_60) < 0)
231                 return -EINVAL;
232
233         venc_enable_vpss_clock(venc->venc_type, VPBE_ENC_STD, V4L2_STD_525_60);
234         venc_enabledigitaloutput(sd, 0);
235
236         if (venc->venc_type == VPBE_VERSION_3) {
237                 venc_write(sd, VENC_CLKCTL, 0x01);
238                 venc_write(sd, VENC_VIDCTL, 0);
239                 vdaccfg_write(sd, VDAC_CONFIG_SD_V3);
240         } else if (venc->venc_type == VPBE_VERSION_2) {
241                 venc_write(sd, VENC_CLKCTL, 0x01);
242                 venc_write(sd, VENC_VIDCTL, 0);
243                 vdaccfg_write(sd, VDAC_CONFIG_SD_V2);
244         } else {
245                 /* to set VENC CLK DIV to 1 - final clock is 54 MHz */
246                 venc_modify(sd, VENC_VIDCTL, 0, 1 << 1);
247                 /* Set REC656 Mode */
248                 venc_write(sd, VENC_YCCCTL, 0x1);
249                 venc_modify(sd, VENC_VDPRO, 0, VENC_VDPRO_DAFRQ);
250                 venc_modify(sd, VENC_VDPRO, 0, VENC_VDPRO_DAUPS);
251         }
252
253         venc_write(sd, VENC_VMOD, 0);
254         venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
255                         VENC_VMOD_VIE);
256         venc_modify(sd, VENC_VMOD, (0 << VENC_VMOD_VMD), VENC_VMOD_VMD);
257         venc_modify(sd, VENC_VMOD, (0 << VENC_VMOD_TVTYP_SHIFT),
258                         VENC_VMOD_TVTYP);
259         venc_write(sd, VENC_DACTST, 0x0);
260         venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
261
262         return 0;
263 }
264
265 /*
266  * setting PAL mode
267  */
268 static int venc_set_pal(struct v4l2_subdev *sd)
269 {
270         struct venc_state *venc = to_state(sd);
271
272         v4l2_dbg(debug, 2, sd, "venc_set_pal\n");
273
274         /* Setup clock at VPSS & VENC for SD */
275         vpss_enable_clock(VPSS_VENC_CLOCK_SEL, 1);
276         if (venc->pdata->setup_clock(VPBE_ENC_STD, V4L2_STD_625_50) < 0)
277                 return -EINVAL;
278
279         venc_enable_vpss_clock(venc->venc_type, VPBE_ENC_STD, V4L2_STD_625_50);
280         venc_enabledigitaloutput(sd, 0);
281
282         if (venc->venc_type == VPBE_VERSION_3) {
283                 venc_write(sd, VENC_CLKCTL, 0x1);
284                 venc_write(sd, VENC_VIDCTL, 0);
285                 vdaccfg_write(sd, VDAC_CONFIG_SD_V3);
286         } else if (venc->venc_type == VPBE_VERSION_2) {
287                 venc_write(sd, VENC_CLKCTL, 0x1);
288                 venc_write(sd, VENC_VIDCTL, 0);
289                 vdaccfg_write(sd, VDAC_CONFIG_SD_V2);
290         } else {
291                 /* to set VENC CLK DIV to 1 - final clock is 54 MHz */
292                 venc_modify(sd, VENC_VIDCTL, 0, 1 << 1);
293                 /* Set REC656 Mode */
294                 venc_write(sd, VENC_YCCCTL, 0x1);
295         }
296
297         venc_modify(sd, VENC_SYNCCTL, 1 << VENC_SYNCCTL_OVD_SHIFT,
298                         VENC_SYNCCTL_OVD);
299         venc_write(sd, VENC_VMOD, 0);
300         venc_modify(sd, VENC_VMOD,
301                         (1 << VENC_VMOD_VIE_SHIFT),
302                         VENC_VMOD_VIE);
303         venc_modify(sd, VENC_VMOD,
304                         (0 << VENC_VMOD_VMD), VENC_VMOD_VMD);
305         venc_modify(sd, VENC_VMOD,
306                         (1 << VENC_VMOD_TVTYP_SHIFT),
307                         VENC_VMOD_TVTYP);
308         venc_write(sd, VENC_DACTST, 0x0);
309         venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
310
311         return 0;
312 }
313
314 #define VDAC_CONFIG_HD_V2       0x081141EF
315 /*
316  * venc_set_480p59_94
317  *
318  * This function configures the video encoder to EDTV(525p) component setting.
319  */
320 static int venc_set_480p59_94(struct v4l2_subdev *sd)
321 {
322         struct venc_state *venc = to_state(sd);
323         struct venc_platform_data *pdata = venc->pdata;
324
325         v4l2_dbg(debug, 2, sd, "venc_set_480p59_94\n");
326         if (venc->venc_type != VPBE_VERSION_1 &&
327             venc->venc_type != VPBE_VERSION_2)
328                 return -EINVAL;
329
330         /* Setup clock at VPSS & VENC for SD */
331         if (pdata->setup_clock(VPBE_ENC_DV_TIMINGS, 27000000) < 0)
332                 return -EINVAL;
333
334         venc_enable_vpss_clock(venc->venc_type, VPBE_ENC_DV_TIMINGS, 27000000);
335         venc_enabledigitaloutput(sd, 0);
336
337         if (venc->venc_type == VPBE_VERSION_2)
338                 vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
339         venc_write(sd, VENC_OSDCLK0, 0);
340         venc_write(sd, VENC_OSDCLK1, 1);
341
342         if (venc->venc_type == VPBE_VERSION_1) {
343                 venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ,
344                             VENC_VDPRO_DAFRQ);
345                 venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS,
346                             VENC_VDPRO_DAUPS);
347         }
348
349         venc_write(sd, VENC_VMOD, 0);
350         venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
351                     VENC_VMOD_VIE);
352         venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD);
353         venc_modify(sd, VENC_VMOD, (HDTV_525P << VENC_VMOD_TVTYP_SHIFT),
354                     VENC_VMOD_TVTYP);
355         venc_modify(sd, VENC_VMOD, VENC_VMOD_VDMD_YCBCR8 <<
356                     VENC_VMOD_VDMD_SHIFT, VENC_VMOD_VDMD);
357
358         venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
359
360         return 0;
361 }
362
363 /*
364  * venc_set_625p
365  *
366  * This function configures the video encoder to HDTV(625p) component setting
367  */
368 static int venc_set_576p50(struct v4l2_subdev *sd)
369 {
370         struct venc_state *venc = to_state(sd);
371         struct venc_platform_data *pdata = venc->pdata;
372
373         v4l2_dbg(debug, 2, sd, "venc_set_576p50\n");
374
375         if (venc->venc_type != VPBE_VERSION_1 &&
376             venc->venc_type != VPBE_VERSION_2)
377                 return -EINVAL;
378         /* Setup clock at VPSS & VENC for SD */
379         if (pdata->setup_clock(VPBE_ENC_DV_TIMINGS, 27000000) < 0)
380                 return -EINVAL;
381
382         venc_enable_vpss_clock(venc->venc_type, VPBE_ENC_DV_TIMINGS, 27000000);
383         venc_enabledigitaloutput(sd, 0);
384
385         if (venc->venc_type == VPBE_VERSION_2)
386                 vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
387
388         venc_write(sd, VENC_OSDCLK0, 0);
389         venc_write(sd, VENC_OSDCLK1, 1);
390
391         if (venc->venc_type == VPBE_VERSION_1) {
392                 venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ,
393                             VENC_VDPRO_DAFRQ);
394                 venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS,
395                             VENC_VDPRO_DAUPS);
396         }
397
398         venc_write(sd, VENC_VMOD, 0);
399         venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
400                     VENC_VMOD_VIE);
401         venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD);
402         venc_modify(sd, VENC_VMOD, (HDTV_625P << VENC_VMOD_TVTYP_SHIFT),
403                     VENC_VMOD_TVTYP);
404
405         venc_modify(sd, VENC_VMOD, VENC_VMOD_VDMD_YCBCR8 <<
406                     VENC_VMOD_VDMD_SHIFT, VENC_VMOD_VDMD);
407         venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
408
409         return 0;
410 }
411
412 /*
413  * venc_set_720p60_internal - Setup 720p60 in venc for dm365 only
414  */
415 static int venc_set_720p60_internal(struct v4l2_subdev *sd)
416 {
417         struct venc_state *venc = to_state(sd);
418         struct venc_platform_data *pdata = venc->pdata;
419
420         if (pdata->setup_clock(VPBE_ENC_DV_TIMINGS, 74250000) < 0)
421                 return -EINVAL;
422
423         venc_enable_vpss_clock(venc->venc_type, VPBE_ENC_DV_TIMINGS, 74250000);
424         venc_enabledigitaloutput(sd, 0);
425
426         venc_write(sd, VENC_OSDCLK0, 0);
427         venc_write(sd, VENC_OSDCLK1, 1);
428
429         venc_write(sd, VENC_VMOD, 0);
430         /* DM365 component HD mode */
431         venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
432             VENC_VMOD_VIE);
433         venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD);
434         venc_modify(sd, VENC_VMOD, (HDTV_720P << VENC_VMOD_TVTYP_SHIFT),
435                     VENC_VMOD_TVTYP);
436         venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
437         venc_write(sd, VENC_XHINTVL, 0);
438         return 0;
439 }
440
441 /*
442  * venc_set_1080i30_internal - Setup 1080i30 in venc for dm365 only
443  */
444 static int venc_set_1080i30_internal(struct v4l2_subdev *sd)
445 {
446         struct venc_state *venc = to_state(sd);
447         struct venc_platform_data *pdata = venc->pdata;
448
449         if (pdata->setup_clock(VPBE_ENC_DV_TIMINGS, 74250000) < 0)
450                 return -EINVAL;
451
452         venc_enable_vpss_clock(venc->venc_type, VPBE_ENC_DV_TIMINGS, 74250000);
453         venc_enabledigitaloutput(sd, 0);
454
455         venc_write(sd, VENC_OSDCLK0, 0);
456         venc_write(sd, VENC_OSDCLK1, 1);
457
458
459         venc_write(sd, VENC_VMOD, 0);
460         /* DM365 component HD mode */
461         venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
462                     VENC_VMOD_VIE);
463         venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD);
464         venc_modify(sd, VENC_VMOD, (HDTV_1080I << VENC_VMOD_TVTYP_SHIFT),
465                     VENC_VMOD_TVTYP);
466         venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
467         venc_write(sd, VENC_XHINTVL, 0);
468         return 0;
469 }
470
471 static int venc_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm)
472 {
473         v4l2_dbg(debug, 1, sd, "venc_s_std_output\n");
474
475         if (norm & V4L2_STD_525_60)
476                 return venc_set_ntsc(sd);
477         else if (norm & V4L2_STD_625_50)
478                 return venc_set_pal(sd);
479
480         return -EINVAL;
481 }
482
483 static int venc_s_dv_timings(struct v4l2_subdev *sd,
484                             struct v4l2_dv_timings *dv_timings)
485 {
486         struct venc_state *venc = to_state(sd);
487         u32 height = dv_timings->bt.height;
488         int ret;
489
490         v4l2_dbg(debug, 1, sd, "venc_s_dv_timings\n");
491
492         if (height == 576)
493                 return venc_set_576p50(sd);
494         else if (height == 480)
495                 return venc_set_480p59_94(sd);
496         else if ((height == 720) &&
497                         (venc->venc_type == VPBE_VERSION_2)) {
498                 /* TBD setup internal 720p mode here */
499                 ret = venc_set_720p60_internal(sd);
500                 /* for DM365 VPBE, there is DAC inside */
501                 vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
502                 return ret;
503         } else if ((height == 1080) &&
504                 (venc->venc_type == VPBE_VERSION_2)) {
505                 /* TBD setup internal 1080i mode here */
506                 ret = venc_set_1080i30_internal(sd);
507                 /* for DM365 VPBE, there is DAC inside */
508                 vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
509                 return ret;
510         }
511         return -EINVAL;
512 }
513
514 static int venc_s_routing(struct v4l2_subdev *sd, u32 input, u32 output,
515                           u32 config)
516 {
517         struct venc_state *venc = to_state(sd);
518         int ret;
519
520         v4l2_dbg(debug, 1, sd, "venc_s_routing\n");
521
522         ret = venc_set_dac(sd, output);
523         if (!ret)
524                 venc->output = output;
525
526         return ret;
527 }
528
529 static long venc_ioctl(struct v4l2_subdev *sd,
530                         unsigned int cmd,
531                         void *arg)
532 {
533         u32 val;
534
535         switch (cmd) {
536         case VENC_GET_FLD:
537                 val = venc_read(sd, VENC_VSTAT);
538                 *((int *)arg) = ((val & VENC_VSTAT_FIDST) ==
539                 VENC_VSTAT_FIDST);
540                 break;
541         default:
542                 v4l2_err(sd, "Wrong IOCTL cmd\n");
543                 break;
544         }
545
546         return 0;
547 }
548
549 static const struct v4l2_subdev_core_ops venc_core_ops = {
550         .ioctl      = venc_ioctl,
551 };
552
553 static const struct v4l2_subdev_video_ops venc_video_ops = {
554         .s_routing = venc_s_routing,
555         .s_std_output = venc_s_std_output,
556         .s_dv_timings = venc_s_dv_timings,
557 };
558
559 static const struct v4l2_subdev_ops venc_ops = {
560         .core = &venc_core_ops,
561         .video = &venc_video_ops,
562 };
563
564 static int venc_initialize(struct v4l2_subdev *sd)
565 {
566         struct venc_state *venc = to_state(sd);
567         int ret;
568
569         /* Set default to output to composite and std to NTSC */
570         venc->output = 0;
571         venc->std = V4L2_STD_525_60;
572
573         ret = venc_s_routing(sd, 0, venc->output, 0);
574         if (ret < 0) {
575                 v4l2_err(sd, "Error setting output during init\n");
576                 return -EINVAL;
577         }
578
579         ret = venc_s_std_output(sd, venc->std);
580         if (ret < 0) {
581                 v4l2_err(sd, "Error setting std during init\n");
582                 return -EINVAL;
583         }
584
585         return ret;
586 }
587
588 static int venc_device_get(struct device *dev, void *data)
589 {
590         struct platform_device *pdev = to_platform_device(dev);
591         struct venc_state **venc = data;
592
593         if (strstr(pdev->name, "vpbe-venc") != NULL)
594                 *venc = platform_get_drvdata(pdev);
595
596         return 0;
597 }
598
599 struct v4l2_subdev *venc_sub_dev_init(struct v4l2_device *v4l2_dev,
600                 const char *venc_name)
601 {
602         struct venc_state *venc = NULL;
603
604         bus_for_each_dev(&platform_bus_type, NULL, &venc,
605                         venc_device_get);
606         if (venc == NULL)
607                 return NULL;
608
609         v4l2_subdev_init(&venc->sd, &venc_ops);
610
611         strscpy(venc->sd.name, venc_name, sizeof(venc->sd.name));
612         if (v4l2_device_register_subdev(v4l2_dev, &venc->sd) < 0) {
613                 v4l2_err(v4l2_dev,
614                         "vpbe unable to register venc sub device\n");
615                 return NULL;
616         }
617         if (venc_initialize(&venc->sd)) {
618                 v4l2_err(v4l2_dev,
619                         "vpbe venc initialization failed\n");
620                 return NULL;
621         }
622
623         return &venc->sd;
624 }
625 EXPORT_SYMBOL(venc_sub_dev_init);
626
627 static int venc_probe(struct platform_device *pdev)
628 {
629         const struct platform_device_id *pdev_id;
630         struct venc_state *venc;
631         struct resource *res;
632
633         if (!pdev->dev.platform_data) {
634                 dev_err(&pdev->dev, "No platform data for VENC sub device");
635                 return -EINVAL;
636         }
637
638         pdev_id = platform_get_device_id(pdev);
639         if (!pdev_id)
640                 return -EINVAL;
641
642         venc = devm_kzalloc(&pdev->dev, sizeof(struct venc_state), GFP_KERNEL);
643         if (venc == NULL)
644                 return -ENOMEM;
645
646         venc->venc_type = pdev_id->driver_data;
647         venc->pdev = &pdev->dev;
648         venc->pdata = pdev->dev.platform_data;
649
650         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
651
652         venc->venc_base = devm_ioremap_resource(&pdev->dev, res);
653         if (IS_ERR(venc->venc_base))
654                 return PTR_ERR(venc->venc_base);
655
656         if (venc->venc_type != VPBE_VERSION_1) {
657                 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
658
659                 venc->vdaccfg_reg = devm_ioremap_resource(&pdev->dev, res);
660                 if (IS_ERR(venc->vdaccfg_reg))
661                         return PTR_ERR(venc->vdaccfg_reg);
662         }
663         spin_lock_init(&venc->lock);
664         platform_set_drvdata(pdev, venc);
665         dev_notice(venc->pdev, "VENC sub device probe success\n");
666
667         return 0;
668 }
669
670 static int venc_remove(struct platform_device *pdev)
671 {
672         return 0;
673 }
674
675 static struct platform_driver venc_driver = {
676         .probe          = venc_probe,
677         .remove         = venc_remove,
678         .driver         = {
679                 .name   = MODULE_NAME,
680         },
681         .id_table       = vpbe_venc_devtype
682 };
683
684 module_platform_driver(venc_driver);
685
686 MODULE_LICENSE("GPL");
687 MODULE_DESCRIPTION("VPBE VENC Driver");
688 MODULE_AUTHOR("Texas Instruments");