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