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