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