vpbe_venc.c (17373B)
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 625 if (!pdev->dev.platform_data) { 626 dev_err(&pdev->dev, "No platform data for VENC sub device"); 627 return -EINVAL; 628 } 629 630 pdev_id = platform_get_device_id(pdev); 631 if (!pdev_id) 632 return -EINVAL; 633 634 venc = devm_kzalloc(&pdev->dev, sizeof(struct venc_state), GFP_KERNEL); 635 if (venc == NULL) 636 return -ENOMEM; 637 638 venc->venc_type = pdev_id->driver_data; 639 venc->pdev = &pdev->dev; 640 venc->pdata = pdev->dev.platform_data; 641 642 venc->venc_base = devm_platform_ioremap_resource(pdev, 0); 643 if (IS_ERR(venc->venc_base)) 644 return PTR_ERR(venc->venc_base); 645 646 if (venc->venc_type != VPBE_VERSION_1) { 647 venc->vdaccfg_reg = devm_platform_ioremap_resource(pdev, 1); 648 if (IS_ERR(venc->vdaccfg_reg)) 649 return PTR_ERR(venc->vdaccfg_reg); 650 } 651 spin_lock_init(&venc->lock); 652 platform_set_drvdata(pdev, venc); 653 dev_notice(venc->pdev, "VENC sub device probe success\n"); 654 655 return 0; 656} 657 658static int venc_remove(struct platform_device *pdev) 659{ 660 return 0; 661} 662 663static struct platform_driver venc_driver = { 664 .probe = venc_probe, 665 .remove = venc_remove, 666 .driver = { 667 .name = MODULE_NAME, 668 }, 669 .id_table = vpbe_venc_devtype 670}; 671 672module_platform_driver(venc_driver); 673 674MODULE_LICENSE("GPL"); 675MODULE_DESCRIPTION("VPBE VENC Driver"); 676MODULE_AUTHOR("Texas Instruments");