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