Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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