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/mod_devicetable.h>
  15#include <linux/kernel.h>
  16#include <linux/init.h>
  17#include <linux/ctype.h>
  18#include <linux/delay.h>
  19#include <linux/device.h>
  20#include <linux/interrupt.h>
  21#include <linux/platform_device.h>
  22#include <linux/videodev2.h>
  23#include <linux/slab.h>
  24
  25#ifdef CONFIG_ARCH_DAVINCI
  26#include <mach/hardware.h>
  27#include <mach/mux.h>
  28#endif
  29
  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 const 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        struct venc_state *venc = to_state(sd);
 232        struct venc_platform_data *pdata = venc->pdata;
 233
 234        v4l2_dbg(debug, 2, sd, "venc_set_ntsc\n");
 235
 236        /* Setup clock at VPSS & VENC for SD */
 237        vpss_enable_clock(VPSS_VENC_CLOCK_SEL, 1);
 238        if (pdata->setup_clock(VPBE_ENC_STD, V4L2_STD_525_60) < 0)
 239                return -EINVAL;
 240
 241        venc_enable_vpss_clock(venc->venc_type, VPBE_ENC_STD, V4L2_STD_525_60);
 242        venc_enabledigitaloutput(sd, 0);
 243
 244        if (venc->venc_type == VPBE_VERSION_3) {
 245                venc_write(sd, VENC_CLKCTL, 0x01);
 246                venc_write(sd, VENC_VIDCTL, 0);
 247                vdaccfg_write(sd, VDAC_CONFIG_SD_V3);
 248        } else if (venc->venc_type == VPBE_VERSION_2) {
 249                venc_write(sd, VENC_CLKCTL, 0x01);
 250                venc_write(sd, VENC_VIDCTL, 0);
 251                vdaccfg_write(sd, VDAC_CONFIG_SD_V2);
 252        } else {
 253                /* to set VENC CLK DIV to 1 - final clock is 54 MHz */
 254                venc_modify(sd, VENC_VIDCTL, 0, 1 << 1);
 255                /* Set REC656 Mode */
 256                venc_write(sd, VENC_YCCCTL, 0x1);
 257                venc_modify(sd, VENC_VDPRO, 0, VENC_VDPRO_DAFRQ);
 258                venc_modify(sd, VENC_VDPRO, 0, VENC_VDPRO_DAUPS);
 259        }
 260
 261        venc_write(sd, VENC_VMOD, 0);
 262        venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
 263                        VENC_VMOD_VIE);
 264        venc_modify(sd, VENC_VMOD, (0 << VENC_VMOD_VMD), VENC_VMOD_VMD);
 265        venc_modify(sd, VENC_VMOD, (0 << VENC_VMOD_TVTYP_SHIFT),
 266                        VENC_VMOD_TVTYP);
 267        venc_write(sd, VENC_DACTST, 0x0);
 268        venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
 269
 270        return 0;
 271}
 272
 273/*
 274 * setting PAL mode
 275 */
 276static int venc_set_pal(struct v4l2_subdev *sd)
 277{
 278        struct venc_state *venc = to_state(sd);
 279
 280        v4l2_dbg(debug, 2, sd, "venc_set_pal\n");
 281
 282        /* Setup clock at VPSS & VENC for SD */
 283        vpss_enable_clock(VPSS_VENC_CLOCK_SEL, 1);
 284        if (venc->pdata->setup_clock(VPBE_ENC_STD, V4L2_STD_625_50) < 0)
 285                return -EINVAL;
 286
 287        venc_enable_vpss_clock(venc->venc_type, VPBE_ENC_STD, V4L2_STD_625_50);
 288        venc_enabledigitaloutput(sd, 0);
 289
 290        if (venc->venc_type == VPBE_VERSION_3) {
 291                venc_write(sd, VENC_CLKCTL, 0x1);
 292                venc_write(sd, VENC_VIDCTL, 0);
 293                vdaccfg_write(sd, VDAC_CONFIG_SD_V3);
 294        } else if (venc->venc_type == VPBE_VERSION_2) {
 295                venc_write(sd, VENC_CLKCTL, 0x1);
 296                venc_write(sd, VENC_VIDCTL, 0);
 297                vdaccfg_write(sd, VDAC_CONFIG_SD_V2);
 298        } else {
 299                /* to set VENC CLK DIV to 1 - final clock is 54 MHz */
 300                venc_modify(sd, VENC_VIDCTL, 0, 1 << 1);
 301                /* Set REC656 Mode */
 302                venc_write(sd, VENC_YCCCTL, 0x1);
 303        }
 304
 305        venc_modify(sd, VENC_SYNCCTL, 1 << VENC_SYNCCTL_OVD_SHIFT,
 306                        VENC_SYNCCTL_OVD);
 307        venc_write(sd, VENC_VMOD, 0);
 308        venc_modify(sd, VENC_VMOD,
 309                        (1 << VENC_VMOD_VIE_SHIFT),
 310                        VENC_VMOD_VIE);
 311        venc_modify(sd, VENC_VMOD,
 312                        (0 << VENC_VMOD_VMD), VENC_VMOD_VMD);
 313        venc_modify(sd, VENC_VMOD,
 314                        (1 << VENC_VMOD_TVTYP_SHIFT),
 315                        VENC_VMOD_TVTYP);
 316        venc_write(sd, VENC_DACTST, 0x0);
 317        venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
 318
 319        return 0;
 320}
 321
 322#define VDAC_CONFIG_HD_V2       0x081141EF
 323/*
 324 * venc_set_480p59_94
 325 *
 326 * This function configures the video encoder to EDTV(525p) component setting.
 327 */
 328static int venc_set_480p59_94(struct v4l2_subdev *sd)
 329{
 330        struct venc_state *venc = to_state(sd);
 331        struct venc_platform_data *pdata = venc->pdata;
 332
 333        v4l2_dbg(debug, 2, sd, "venc_set_480p59_94\n");
 334        if (venc->venc_type != VPBE_VERSION_1 &&
 335            venc->venc_type != VPBE_VERSION_2)
 336                return -EINVAL;
 337
 338        /* Setup clock at VPSS & VENC for SD */
 339        if (pdata->setup_clock(VPBE_ENC_DV_TIMINGS, 27000000) < 0)
 340                return -EINVAL;
 341
 342        venc_enable_vpss_clock(venc->venc_type, VPBE_ENC_DV_TIMINGS, 27000000);
 343        venc_enabledigitaloutput(sd, 0);
 344
 345        if (venc->venc_type == VPBE_VERSION_2)
 346                vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
 347        venc_write(sd, VENC_OSDCLK0, 0);
 348        venc_write(sd, VENC_OSDCLK1, 1);
 349
 350        if (venc->venc_type == VPBE_VERSION_1) {
 351                venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ,
 352                            VENC_VDPRO_DAFRQ);
 353                venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS,
 354                            VENC_VDPRO_DAUPS);
 355        }
 356
 357        venc_write(sd, VENC_VMOD, 0);
 358        venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
 359                    VENC_VMOD_VIE);
 360        venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD);
 361        venc_modify(sd, VENC_VMOD, (HDTV_525P << VENC_VMOD_TVTYP_SHIFT),
 362                    VENC_VMOD_TVTYP);
 363        venc_modify(sd, VENC_VMOD, VENC_VMOD_VDMD_YCBCR8 <<
 364                    VENC_VMOD_VDMD_SHIFT, VENC_VMOD_VDMD);
 365
 366        venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
 367
 368        return 0;
 369}
 370
 371/*
 372 * venc_set_625p
 373 *
 374 * This function configures the video encoder to HDTV(625p) component setting
 375 */
 376static int venc_set_576p50(struct v4l2_subdev *sd)
 377{
 378        struct venc_state *venc = to_state(sd);
 379        struct venc_platform_data *pdata = venc->pdata;
 380
 381        v4l2_dbg(debug, 2, sd, "venc_set_576p50\n");
 382
 383        if (venc->venc_type != VPBE_VERSION_1 &&
 384            venc->venc_type != VPBE_VERSION_2)
 385                return -EINVAL;
 386        /* Setup clock at VPSS & VENC for SD */
 387        if (pdata->setup_clock(VPBE_ENC_DV_TIMINGS, 27000000) < 0)
 388                return -EINVAL;
 389
 390        venc_enable_vpss_clock(venc->venc_type, VPBE_ENC_DV_TIMINGS, 27000000);
 391        venc_enabledigitaloutput(sd, 0);
 392
 393        if (venc->venc_type == VPBE_VERSION_2)
 394                vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
 395
 396        venc_write(sd, VENC_OSDCLK0, 0);
 397        venc_write(sd, VENC_OSDCLK1, 1);
 398
 399        if (venc->venc_type == VPBE_VERSION_1) {
 400                venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ,
 401                            VENC_VDPRO_DAFRQ);
 402                venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS,
 403                            VENC_VDPRO_DAUPS);
 404        }
 405
 406        venc_write(sd, VENC_VMOD, 0);
 407        venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
 408                    VENC_VMOD_VIE);
 409        venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD);
 410        venc_modify(sd, VENC_VMOD, (HDTV_625P << VENC_VMOD_TVTYP_SHIFT),
 411                    VENC_VMOD_TVTYP);
 412
 413        venc_modify(sd, VENC_VMOD, VENC_VMOD_VDMD_YCBCR8 <<
 414                    VENC_VMOD_VDMD_SHIFT, VENC_VMOD_VDMD);
 415        venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
 416
 417        return 0;
 418}
 419
 420/*
 421 * venc_set_720p60_internal - Setup 720p60 in venc for dm365 only
 422 */
 423static int venc_set_720p60_internal(struct v4l2_subdev *sd)
 424{
 425        struct venc_state *venc = to_state(sd);
 426        struct venc_platform_data *pdata = venc->pdata;
 427
 428        if (pdata->setup_clock(VPBE_ENC_DV_TIMINGS, 74250000) < 0)
 429                return -EINVAL;
 430
 431        venc_enable_vpss_clock(venc->venc_type, VPBE_ENC_DV_TIMINGS, 74250000);
 432        venc_enabledigitaloutput(sd, 0);
 433
 434        venc_write(sd, VENC_OSDCLK0, 0);
 435        venc_write(sd, VENC_OSDCLK1, 1);
 436
 437        venc_write(sd, VENC_VMOD, 0);
 438        /* DM365 component HD mode */
 439        venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
 440            VENC_VMOD_VIE);
 441        venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD);
 442        venc_modify(sd, VENC_VMOD, (HDTV_720P << VENC_VMOD_TVTYP_SHIFT),
 443                    VENC_VMOD_TVTYP);
 444        venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
 445        venc_write(sd, VENC_XHINTVL, 0);
 446        return 0;
 447}
 448
 449/*
 450 * venc_set_1080i30_internal - Setup 1080i30 in venc for dm365 only
 451 */
 452static int venc_set_1080i30_internal(struct v4l2_subdev *sd)
 453{
 454        struct venc_state *venc = to_state(sd);
 455        struct venc_platform_data *pdata = venc->pdata;
 456
 457        if (pdata->setup_clock(VPBE_ENC_DV_TIMINGS, 74250000) < 0)
 458                return -EINVAL;
 459
 460        venc_enable_vpss_clock(venc->venc_type, VPBE_ENC_DV_TIMINGS, 74250000);
 461        venc_enabledigitaloutput(sd, 0);
 462
 463        venc_write(sd, VENC_OSDCLK0, 0);
 464        venc_write(sd, VENC_OSDCLK1, 1);
 465
 466
 467        venc_write(sd, VENC_VMOD, 0);
 468        /* DM365 component HD mode */
 469        venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT),
 470                    VENC_VMOD_VIE);
 471        venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD);
 472        venc_modify(sd, VENC_VMOD, (HDTV_1080I << VENC_VMOD_TVTYP_SHIFT),
 473                    VENC_VMOD_TVTYP);
 474        venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC);
 475        venc_write(sd, VENC_XHINTVL, 0);
 476        return 0;
 477}
 478
 479static int venc_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm)
 480{
 481        v4l2_dbg(debug, 1, sd, "venc_s_std_output\n");
 482
 483        if (norm & V4L2_STD_525_60)
 484                return venc_set_ntsc(sd);
 485        else if (norm & V4L2_STD_625_50)
 486                return venc_set_pal(sd);
 487
 488        return -EINVAL;
 489}
 490
 491static int venc_s_dv_timings(struct v4l2_subdev *sd,
 492                            struct v4l2_dv_timings *dv_timings)
 493{
 494        struct venc_state *venc = to_state(sd);
 495        u32 height = dv_timings->bt.height;
 496        int ret;
 497
 498        v4l2_dbg(debug, 1, sd, "venc_s_dv_timings\n");
 499
 500        if (height == 576)
 501                return venc_set_576p50(sd);
 502        else if (height == 480)
 503                return venc_set_480p59_94(sd);
 504        else if ((height == 720) &&
 505                        (venc->venc_type == VPBE_VERSION_2)) {
 506                /* TBD setup internal 720p mode here */
 507                ret = venc_set_720p60_internal(sd);
 508                /* for DM365 VPBE, there is DAC inside */
 509                vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
 510                return ret;
 511        } else if ((height == 1080) &&
 512                (venc->venc_type == VPBE_VERSION_2)) {
 513                /* TBD setup internal 1080i mode here */
 514                ret = venc_set_1080i30_internal(sd);
 515                /* for DM365 VPBE, there is DAC inside */
 516                vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
 517                return ret;
 518        }
 519        return -EINVAL;
 520}
 521
 522static int venc_s_routing(struct v4l2_subdev *sd, u32 input, u32 output,
 523                          u32 config)
 524{
 525        struct venc_state *venc = to_state(sd);
 526        int ret;
 527
 528        v4l2_dbg(debug, 1, sd, "venc_s_routing\n");
 529
 530        ret = venc_set_dac(sd, output);
 531        if (!ret)
 532                venc->output = output;
 533
 534        return ret;
 535}
 536
 537static long venc_ioctl(struct v4l2_subdev *sd,
 538                        unsigned int cmd,
 539                        void *arg)
 540{
 541        u32 val;
 542
 543        switch (cmd) {
 544        case VENC_GET_FLD:
 545                val = venc_read(sd, VENC_VSTAT);
 546                *((int *)arg) = ((val & VENC_VSTAT_FIDST) ==
 547                VENC_VSTAT_FIDST);
 548                break;
 549        default:
 550                v4l2_err(sd, "Wrong IOCTL cmd\n");
 551                break;
 552        }
 553
 554        return 0;
 555}
 556
 557static const struct v4l2_subdev_core_ops venc_core_ops = {
 558        .ioctl      = venc_ioctl,
 559};
 560
 561static const struct v4l2_subdev_video_ops venc_video_ops = {
 562        .s_routing = venc_s_routing,
 563        .s_std_output = venc_s_std_output,
 564        .s_dv_timings = venc_s_dv_timings,
 565};
 566
 567static const struct v4l2_subdev_ops venc_ops = {
 568        .core = &venc_core_ops,
 569        .video = &venc_video_ops,
 570};
 571
 572static int venc_initialize(struct v4l2_subdev *sd)
 573{
 574        struct venc_state *venc = to_state(sd);
 575        int ret;
 576
 577        /* Set default to output to composite and std to NTSC */
 578        venc->output = 0;
 579        venc->std = V4L2_STD_525_60;
 580
 581        ret = venc_s_routing(sd, 0, venc->output, 0);
 582        if (ret < 0) {
 583                v4l2_err(sd, "Error setting output during init\n");
 584                return -EINVAL;
 585        }
 586
 587        ret = venc_s_std_output(sd, venc->std);
 588        if (ret < 0) {
 589                v4l2_err(sd, "Error setting std during init\n");
 590                return -EINVAL;
 591        }
 592
 593        return ret;
 594}
 595
 596static int venc_device_get(struct device *dev, void *data)
 597{
 598        struct platform_device *pdev = to_platform_device(dev);
 599        struct venc_state **venc = data;
 600
 601        if (strstr(pdev->name, "vpbe-venc") != NULL)
 602                *venc = platform_get_drvdata(pdev);
 603
 604        return 0;
 605}
 606
 607struct v4l2_subdev *venc_sub_dev_init(struct v4l2_device *v4l2_dev,
 608                const char *venc_name)
 609{
 610        struct venc_state *venc = NULL;
 611
 612        bus_for_each_dev(&platform_bus_type, NULL, &venc,
 613                        venc_device_get);
 614        if (venc == NULL)
 615                return NULL;
 616
 617        v4l2_subdev_init(&venc->sd, &venc_ops);
 618
 619        strscpy(venc->sd.name, venc_name, sizeof(venc->sd.name));
 620        if (v4l2_device_register_subdev(v4l2_dev, &venc->sd) < 0) {
 621                v4l2_err(v4l2_dev,
 622                        "vpbe unable to register venc sub device\n");
 623                return NULL;
 624        }
 625        if (venc_initialize(&venc->sd)) {
 626                v4l2_err(v4l2_dev,
 627                        "vpbe venc initialization failed\n");
 628                return NULL;
 629        }
 630
 631        return &venc->sd;
 632}
 633EXPORT_SYMBOL(venc_sub_dev_init);
 634
 635static int venc_probe(struct platform_device *pdev)
 636{
 637        const struct platform_device_id *pdev_id;
 638        struct venc_state *venc;
 639        struct resource *res;
 640
 641        if (!pdev->dev.platform_data) {
 642                dev_err(&pdev->dev, "No platform data for VENC sub device");
 643                return -EINVAL;
 644        }
 645
 646        pdev_id = platform_get_device_id(pdev);
 647        if (!pdev_id)
 648                return -EINVAL;
 649
 650        venc = devm_kzalloc(&pdev->dev, sizeof(struct venc_state), GFP_KERNEL);
 651        if (venc == NULL)
 652                return -ENOMEM;
 653
 654        venc->venc_type = pdev_id->driver_data;
 655        venc->pdev = &pdev->dev;
 656        venc->pdata = pdev->dev.platform_data;
 657
 658        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 659
 660        venc->venc_base = devm_ioremap_resource(&pdev->dev, res);
 661        if (IS_ERR(venc->venc_base))
 662                return PTR_ERR(venc->venc_base);
 663
 664        if (venc->venc_type != VPBE_VERSION_1) {
 665                res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 666
 667                venc->vdaccfg_reg = devm_ioremap_resource(&pdev->dev, res);
 668                if (IS_ERR(venc->vdaccfg_reg))
 669                        return PTR_ERR(venc->vdaccfg_reg);
 670        }
 671        spin_lock_init(&venc->lock);
 672        platform_set_drvdata(pdev, venc);
 673        dev_notice(venc->pdev, "VENC sub device probe success\n");
 674
 675        return 0;
 676}
 677
 678static int venc_remove(struct platform_device *pdev)
 679{
 680        return 0;
 681}
 682
 683static struct platform_driver venc_driver = {
 684        .probe          = venc_probe,
 685        .remove         = venc_remove,
 686        .driver         = {
 687                .name   = MODULE_NAME,
 688        },
 689        .id_table       = vpbe_venc_devtype
 690};
 691
 692module_platform_driver(venc_driver);
 693
 694MODULE_LICENSE("GPL");
 695MODULE_DESCRIPTION("VPBE VENC Driver");
 696MODULE_AUTHOR("Texas Instruments");
 697