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