linux/drivers/media/video/adv7343.c
<<
>>
Prefs
   1/*
   2 * adv7343 - ADV7343 Video Encoder Driver
   3 *
   4 * The encoder hardware does not support SECAM.
   5 *
   6 * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation version 2.
  11 *
  12 * This program is distributed .as is. WITHOUT ANY WARRANTY of any
  13 * kind, whether express or implied; without even the implied warranty
  14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 */
  17
  18#include <linux/kernel.h>
  19#include <linux/init.h>
  20#include <linux/ctype.h>
  21#include <linux/i2c.h>
  22#include <linux/device.h>
  23#include <linux/delay.h>
  24#include <linux/module.h>
  25#include <linux/videodev2.h>
  26#include <linux/uaccess.h>
  27
  28#include <media/adv7343.h>
  29#include <media/v4l2-device.h>
  30#include <media/v4l2-chip-ident.h>
  31
  32#include "adv7343_regs.h"
  33
  34MODULE_DESCRIPTION("ADV7343 video encoder driver");
  35MODULE_LICENSE("GPL");
  36
  37static int debug;
  38module_param(debug, int, 0644);
  39MODULE_PARM_DESC(debug, "Debug level 0-1");
  40
  41struct adv7343_state {
  42        struct v4l2_subdev sd;
  43        u8 reg00;
  44        u8 reg01;
  45        u8 reg02;
  46        u8 reg35;
  47        u8 reg80;
  48        u8 reg82;
  49        int bright;
  50        int hue;
  51        int gain;
  52        u32 output;
  53        v4l2_std_id std;
  54};
  55
  56static inline struct adv7343_state *to_state(struct v4l2_subdev *sd)
  57{
  58        return container_of(sd, struct adv7343_state, sd);
  59}
  60
  61static inline int adv7343_write(struct v4l2_subdev *sd, u8 reg, u8 value)
  62{
  63        struct i2c_client *client = v4l2_get_subdevdata(sd);
  64
  65        return i2c_smbus_write_byte_data(client, reg, value);
  66}
  67
  68static const u8 adv7343_init_reg_val[] = {
  69        ADV7343_SOFT_RESET, ADV7343_SOFT_RESET_DEFAULT,
  70        ADV7343_POWER_MODE_REG, ADV7343_POWER_MODE_REG_DEFAULT,
  71
  72        ADV7343_HD_MODE_REG1, ADV7343_HD_MODE_REG1_DEFAULT,
  73        ADV7343_HD_MODE_REG2, ADV7343_HD_MODE_REG2_DEFAULT,
  74        ADV7343_HD_MODE_REG3, ADV7343_HD_MODE_REG3_DEFAULT,
  75        ADV7343_HD_MODE_REG4, ADV7343_HD_MODE_REG4_DEFAULT,
  76        ADV7343_HD_MODE_REG5, ADV7343_HD_MODE_REG5_DEFAULT,
  77        ADV7343_HD_MODE_REG6, ADV7343_HD_MODE_REG6_DEFAULT,
  78        ADV7343_HD_MODE_REG7, ADV7343_HD_MODE_REG7_DEFAULT,
  79
  80        ADV7343_SD_MODE_REG1, ADV7343_SD_MODE_REG1_DEFAULT,
  81        ADV7343_SD_MODE_REG2, ADV7343_SD_MODE_REG2_DEFAULT,
  82        ADV7343_SD_MODE_REG3, ADV7343_SD_MODE_REG3_DEFAULT,
  83        ADV7343_SD_MODE_REG4, ADV7343_SD_MODE_REG4_DEFAULT,
  84        ADV7343_SD_MODE_REG5, ADV7343_SD_MODE_REG5_DEFAULT,
  85        ADV7343_SD_MODE_REG6, ADV7343_SD_MODE_REG6_DEFAULT,
  86        ADV7343_SD_MODE_REG7, ADV7343_SD_MODE_REG7_DEFAULT,
  87        ADV7343_SD_MODE_REG8, ADV7343_SD_MODE_REG8_DEFAULT,
  88
  89        ADV7343_SD_HUE_REG, ADV7343_SD_HUE_REG_DEFAULT,
  90        ADV7343_SD_CGMS_WSS0, ADV7343_SD_CGMS_WSS0_DEFAULT,
  91        ADV7343_SD_BRIGHTNESS_WSS, ADV7343_SD_BRIGHTNESS_WSS_DEFAULT,
  92};
  93
  94/*
  95 *                          2^32
  96 * FSC(reg) =  FSC (HZ) * --------
  97 *                        27000000
  98 */
  99static const struct adv7343_std_info stdinfo[] = {
 100        {
 101                /* FSC(Hz) = 3,579,545.45 Hz */
 102                SD_STD_NTSC, 569408542, V4L2_STD_NTSC,
 103        }, {
 104                /* FSC(Hz) = 3,575,611.00 Hz */
 105                SD_STD_PAL_M, 568782678, V4L2_STD_PAL_M,
 106        }, {
 107                /* FSC(Hz) = 3,582,056.00 */
 108                SD_STD_PAL_N, 569807903, V4L2_STD_PAL_Nc,
 109        }, {
 110                /* FSC(Hz) = 4,433,618.75 Hz */
 111                SD_STD_PAL_N, 705268427, V4L2_STD_PAL_N,
 112        }, {
 113                /* FSC(Hz) = 4,433,618.75 Hz */
 114                SD_STD_PAL_BDGHI, 705268427, V4L2_STD_PAL,
 115        }, {
 116                /* FSC(Hz) = 4,433,618.75 Hz */
 117                SD_STD_NTSC, 705268427, V4L2_STD_NTSC_443,
 118        }, {
 119                /* FSC(Hz) = 4,433,618.75 Hz */
 120                SD_STD_PAL_M, 705268427, V4L2_STD_PAL_60,
 121        },
 122};
 123
 124static int adv7343_setstd(struct v4l2_subdev *sd, v4l2_std_id std)
 125{
 126        struct adv7343_state *state = to_state(sd);
 127        struct adv7343_std_info *std_info;
 128        int output_idx, num_std;
 129        char *fsc_ptr;
 130        u8 reg, val;
 131        int err = 0;
 132        int i = 0;
 133
 134        output_idx = state->output;
 135
 136        std_info = (struct adv7343_std_info *)stdinfo;
 137        num_std = ARRAY_SIZE(stdinfo);
 138
 139        for (i = 0; i < num_std; i++) {
 140                if (std_info[i].stdid & std)
 141                        break;
 142        }
 143
 144        if (i == num_std) {
 145                v4l2_dbg(1, debug, sd,
 146                                "Invalid std or std is not supported: %llx\n",
 147                                                (unsigned long long)std);
 148                return -EINVAL;
 149        }
 150
 151        /* Set the standard */
 152        val = state->reg80 & (~(SD_STD_MASK));
 153        val |= std_info[i].standard_val3;
 154        err = adv7343_write(sd, ADV7343_SD_MODE_REG1, val);
 155        if (err < 0)
 156                goto setstd_exit;
 157
 158        state->reg80 = val;
 159
 160        /* Configure the input mode register */
 161        val = state->reg01 & (~((u8) INPUT_MODE_MASK));
 162        val |= SD_INPUT_MODE;
 163        err = adv7343_write(sd, ADV7343_MODE_SELECT_REG, val);
 164        if (err < 0)
 165                goto setstd_exit;
 166
 167        state->reg01 = val;
 168
 169        /* Program the sub carrier frequency registers */
 170        fsc_ptr = (unsigned char *)&std_info[i].fsc_val;
 171        reg = ADV7343_FSC_REG0;
 172        for (i = 0; i < 4; i++, reg++, fsc_ptr++) {
 173                err = adv7343_write(sd, reg, *fsc_ptr);
 174                if (err < 0)
 175                        goto setstd_exit;
 176        }
 177
 178        val = state->reg80;
 179
 180        /* Filter settings */
 181        if (std & (V4L2_STD_NTSC | V4L2_STD_NTSC_443))
 182                val &= 0x03;
 183        else if (std & ~V4L2_STD_SECAM)
 184                val |= 0x04;
 185
 186        err = adv7343_write(sd, ADV7343_SD_MODE_REG1, val);
 187        if (err < 0)
 188                goto setstd_exit;
 189
 190        state->reg80 = val;
 191
 192setstd_exit:
 193        if (err != 0)
 194                v4l2_err(sd, "Error setting std, write failed\n");
 195
 196        return err;
 197}
 198
 199static int adv7343_setoutput(struct v4l2_subdev *sd, u32 output_type)
 200{
 201        struct adv7343_state *state = to_state(sd);
 202        unsigned char val;
 203        int err = 0;
 204
 205        if (output_type > ADV7343_SVIDEO_ID) {
 206                v4l2_dbg(1, debug, sd,
 207                        "Invalid output type or output type not supported:%d\n",
 208                                                                output_type);
 209                return -EINVAL;
 210        }
 211
 212        /* Enable Appropriate DAC */
 213        val = state->reg00 & 0x03;
 214
 215        if (output_type == ADV7343_COMPOSITE_ID)
 216                val |= ADV7343_COMPOSITE_POWER_VALUE;
 217        else if (output_type == ADV7343_COMPONENT_ID)
 218                val |= ADV7343_COMPONENT_POWER_VALUE;
 219        else
 220                val |= ADV7343_SVIDEO_POWER_VALUE;
 221
 222        err = adv7343_write(sd, ADV7343_POWER_MODE_REG, val);
 223        if (err < 0)
 224                goto setoutput_exit;
 225
 226        state->reg00 = val;
 227
 228        /* Enable YUV output */
 229        val = state->reg02 | YUV_OUTPUT_SELECT;
 230        err = adv7343_write(sd, ADV7343_MODE_REG0, val);
 231        if (err < 0)
 232                goto setoutput_exit;
 233
 234        state->reg02 = val;
 235
 236        /* configure SD DAC Output 2 and SD DAC Output 1 bit to zero */
 237        val = state->reg82 & (SD_DAC_1_DI & SD_DAC_2_DI);
 238        err = adv7343_write(sd, ADV7343_SD_MODE_REG2, val);
 239        if (err < 0)
 240                goto setoutput_exit;
 241
 242        state->reg82 = val;
 243
 244        /* configure ED/HD Color DAC Swap and ED/HD RGB Input Enable bit to
 245         * zero */
 246        val = state->reg35 & (HD_RGB_INPUT_DI & HD_DAC_SWAP_DI);
 247        err = adv7343_write(sd, ADV7343_HD_MODE_REG6, val);
 248        if (err < 0)
 249                goto setoutput_exit;
 250
 251        state->reg35 = val;
 252
 253setoutput_exit:
 254        if (err != 0)
 255                v4l2_err(sd, "Error setting output, write failed\n");
 256
 257        return err;
 258}
 259
 260static int adv7343_log_status(struct v4l2_subdev *sd)
 261{
 262        struct adv7343_state *state = to_state(sd);
 263
 264        v4l2_info(sd, "Standard: %llx\n", (unsigned long long)state->std);
 265        v4l2_info(sd, "Output: %s\n", (state->output == 0) ? "Composite" :
 266                        ((state->output == 1) ? "Component" : "S-Video"));
 267        return 0;
 268}
 269
 270static int adv7343_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
 271{
 272        switch (qc->id) {
 273        case V4L2_CID_BRIGHTNESS:
 274                return v4l2_ctrl_query_fill(qc, ADV7343_BRIGHTNESS_MIN,
 275                                                ADV7343_BRIGHTNESS_MAX, 1,
 276                                                ADV7343_BRIGHTNESS_DEF);
 277        case V4L2_CID_HUE:
 278                return v4l2_ctrl_query_fill(qc, ADV7343_HUE_MIN,
 279                                                ADV7343_HUE_MAX, 1 ,
 280                                                ADV7343_HUE_DEF);
 281        case V4L2_CID_GAIN:
 282                return v4l2_ctrl_query_fill(qc, ADV7343_GAIN_MIN,
 283                                                ADV7343_GAIN_MAX, 1,
 284                                                ADV7343_GAIN_DEF);
 285        default:
 286                break;
 287        }
 288
 289        return 0;
 290}
 291
 292static int adv7343_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 293{
 294        struct adv7343_state *state = to_state(sd);
 295        int err = 0;
 296
 297        switch (ctrl->id) {
 298        case V4L2_CID_BRIGHTNESS:
 299                if (ctrl->value < ADV7343_BRIGHTNESS_MIN ||
 300                                        ctrl->value > ADV7343_BRIGHTNESS_MAX) {
 301                        v4l2_dbg(1, debug, sd,
 302                                        "invalid brightness settings %d\n",
 303                                                                ctrl->value);
 304                        return -ERANGE;
 305                }
 306
 307                state->bright = ctrl->value;
 308                err = adv7343_write(sd, ADV7343_SD_BRIGHTNESS_WSS,
 309                                        state->bright);
 310                break;
 311
 312        case V4L2_CID_HUE:
 313                if (ctrl->value < ADV7343_HUE_MIN ||
 314                                        ctrl->value > ADV7343_HUE_MAX) {
 315                        v4l2_dbg(1, debug, sd, "invalid hue settings %d\n",
 316                                                                ctrl->value);
 317                        return -ERANGE;
 318                }
 319
 320                state->hue = ctrl->value;
 321                err = adv7343_write(sd, ADV7343_SD_HUE_REG, state->hue);
 322                break;
 323
 324        case V4L2_CID_GAIN:
 325                if (ctrl->value < ADV7343_GAIN_MIN ||
 326                                        ctrl->value > ADV7343_GAIN_MAX) {
 327                        v4l2_dbg(1, debug, sd, "invalid gain settings %d\n",
 328                                                                ctrl->value);
 329                        return -ERANGE;
 330                }
 331
 332                if ((ctrl->value > POSITIVE_GAIN_MAX) &&
 333                        (ctrl->value < NEGATIVE_GAIN_MIN)) {
 334                        v4l2_dbg(1, debug, sd,
 335                                "gain settings not within the specified range\n");
 336                        return -ERANGE;
 337                }
 338
 339                state->gain = ctrl->value;
 340                err = adv7343_write(sd, ADV7343_DAC2_OUTPUT_LEVEL, state->gain);
 341                break;
 342
 343        default:
 344                return -EINVAL;
 345        }
 346
 347        if (err < 0)
 348                v4l2_err(sd, "Failed to set the encoder controls\n");
 349
 350        return err;
 351}
 352
 353static int adv7343_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
 354{
 355        struct adv7343_state *state = to_state(sd);
 356
 357        switch (ctrl->id) {
 358        case V4L2_CID_BRIGHTNESS:
 359                ctrl->value = state->bright;
 360                break;
 361
 362        case V4L2_CID_HUE:
 363                ctrl->value = state->hue;
 364                break;
 365
 366        case V4L2_CID_GAIN:
 367                ctrl->value = state->gain;
 368                break;
 369
 370        default:
 371                return -EINVAL;
 372        }
 373
 374        return 0;
 375}
 376
 377static int adv7343_g_chip_ident(struct v4l2_subdev *sd,
 378                                struct v4l2_dbg_chip_ident *chip)
 379{
 380        struct i2c_client *client = v4l2_get_subdevdata(sd);
 381
 382        return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7343, 0);
 383}
 384
 385static const struct v4l2_subdev_core_ops adv7343_core_ops = {
 386        .log_status     = adv7343_log_status,
 387        .g_chip_ident   = adv7343_g_chip_ident,
 388        .g_ctrl         = adv7343_g_ctrl,
 389        .s_ctrl         = adv7343_s_ctrl,
 390        .queryctrl      = adv7343_queryctrl,
 391};
 392
 393static int adv7343_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
 394{
 395        struct adv7343_state *state = to_state(sd);
 396        int err = 0;
 397
 398        if (state->std == std)
 399                return 0;
 400
 401        err = adv7343_setstd(sd, std);
 402        if (!err)
 403                state->std = std;
 404
 405        return err;
 406}
 407
 408static int adv7343_s_routing(struct v4l2_subdev *sd,
 409                u32 input, u32 output, u32 config)
 410{
 411        struct adv7343_state *state = to_state(sd);
 412        int err = 0;
 413
 414        if (state->output == output)
 415                return 0;
 416
 417        err = adv7343_setoutput(sd, output);
 418        if (!err)
 419                state->output = output;
 420
 421        return err;
 422}
 423
 424static const struct v4l2_subdev_video_ops adv7343_video_ops = {
 425        .s_std_output   = adv7343_s_std_output,
 426        .s_routing      = adv7343_s_routing,
 427};
 428
 429static const struct v4l2_subdev_ops adv7343_ops = {
 430        .core   = &adv7343_core_ops,
 431        .video  = &adv7343_video_ops,
 432};
 433
 434static int adv7343_initialize(struct v4l2_subdev *sd)
 435{
 436        struct adv7343_state *state = to_state(sd);
 437        int err = 0;
 438        int i;
 439
 440        for (i = 0; i < ARRAY_SIZE(adv7343_init_reg_val); i += 2) {
 441
 442                err = adv7343_write(sd, adv7343_init_reg_val[i],
 443                                        adv7343_init_reg_val[i+1]);
 444                if (err) {
 445                        v4l2_err(sd, "Error initializing\n");
 446                        return err;
 447                }
 448        }
 449
 450        /* Configure for default video standard */
 451        err = adv7343_setoutput(sd, state->output);
 452        if (err < 0) {
 453                v4l2_err(sd, "Error setting output during init\n");
 454                return -EINVAL;
 455        }
 456
 457        err = adv7343_setstd(sd, state->std);
 458        if (err < 0) {
 459                v4l2_err(sd, "Error setting std during init\n");
 460                return -EINVAL;
 461        }
 462
 463        return err;
 464}
 465
 466static int adv7343_probe(struct i2c_client *client,
 467                                const struct i2c_device_id *id)
 468{
 469        struct adv7343_state *state;
 470
 471        if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 472                return -ENODEV;
 473
 474        v4l_info(client, "chip found @ 0x%x (%s)\n",
 475                        client->addr << 1, client->adapter->name);
 476
 477        state = kzalloc(sizeof(struct adv7343_state), GFP_KERNEL);
 478        if (state == NULL)
 479                return -ENOMEM;
 480
 481        state->reg00    = 0x80;
 482        state->reg01    = 0x00;
 483        state->reg02    = 0x20;
 484        state->reg35    = 0x00;
 485        state->reg80    = ADV7343_SD_MODE_REG1_DEFAULT;
 486        state->reg82    = ADV7343_SD_MODE_REG2_DEFAULT;
 487
 488        state->output = ADV7343_COMPOSITE_ID;
 489        state->std = V4L2_STD_NTSC;
 490
 491        v4l2_i2c_subdev_init(&state->sd, client, &adv7343_ops);
 492        return adv7343_initialize(&state->sd);
 493}
 494
 495static int adv7343_remove(struct i2c_client *client)
 496{
 497        struct v4l2_subdev *sd = i2c_get_clientdata(client);
 498
 499        v4l2_device_unregister_subdev(sd);
 500        kfree(to_state(sd));
 501
 502        return 0;
 503}
 504
 505static const struct i2c_device_id adv7343_id[] = {
 506        {"adv7343", 0},
 507        {},
 508};
 509
 510MODULE_DEVICE_TABLE(i2c, adv7343_id);
 511
 512static struct i2c_driver adv7343_driver = {
 513        .driver = {
 514                .owner  = THIS_MODULE,
 515                .name   = "adv7343",
 516        },
 517        .probe          = adv7343_probe,
 518        .remove         = adv7343_remove,
 519        .id_table       = adv7343_id,
 520};
 521
 522static __init int init_adv7343(void)
 523{
 524        return i2c_add_driver(&adv7343_driver);
 525}
 526
 527static __exit void exit_adv7343(void)
 528{
 529        i2c_del_driver(&adv7343_driver);
 530}
 531
 532module_init(init_adv7343);
 533module_exit(exit_adv7343);
 534