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