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