linux/drivers/media/i2c/ths7303.c
<<
>>
Prefs
   1/*
   2 * ths7303/53- THS7303/53 Video Amplifier driver
   3 *
   4 * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
   5 * Copyright 2013 Cisco Systems, Inc. and/or its affiliates.
   6 *
   7 * Author: Chaithrika U S <chaithrika@ti.com>
   8 *
   9 * Contributors:
  10 *     Hans Verkuil <hans.verkuil@cisco.com>
  11 *     Lad, Prabhakar <prabhakar.lad@ti.com>
  12 *     Martin Bugge <marbugge@cisco.com>
  13 *
  14 * This program is free software; you can redistribute it and/or
  15 * modify it under the terms of the GNU General Public License as
  16 * published by the Free Software Foundation version 2.
  17 *
  18 * This program is distributed .as is. WITHOUT ANY WARRANTY of any
  19 * kind, whether express or implied; without even the implied warranty
  20 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21 * GNU General Public License for more details.
  22 */
  23
  24#include <linux/i2c.h>
  25#include <linux/module.h>
  26#include <linux/slab.h>
  27
  28#include <media/ths7303.h>
  29#include <media/v4l2-chip-ident.h>
  30#include <media/v4l2-device.h>
  31
  32#define THS7303_CHANNEL_1       1
  33#define THS7303_CHANNEL_2       2
  34#define THS7303_CHANNEL_3       3
  35
  36struct ths7303_state {
  37        struct v4l2_subdev              sd;
  38        struct ths7303_platform_data    pdata;
  39        struct v4l2_bt_timings          bt;
  40        int std_id;
  41        int stream_on;
  42        int driver_data;
  43};
  44
  45enum ths7303_filter_mode {
  46        THS7303_FILTER_MODE_480I_576I,
  47        THS7303_FILTER_MODE_480P_576P,
  48        THS7303_FILTER_MODE_720P_1080I,
  49        THS7303_FILTER_MODE_1080P,
  50        THS7303_FILTER_MODE_DISABLE
  51};
  52
  53MODULE_DESCRIPTION("TI THS7303 video amplifier driver");
  54MODULE_AUTHOR("Chaithrika U S");
  55MODULE_LICENSE("GPL");
  56
  57static int debug;
  58module_param(debug, int, 0644);
  59MODULE_PARM_DESC(debug, "Debug level 0-1");
  60
  61static inline struct ths7303_state *to_state(struct v4l2_subdev *sd)
  62{
  63        return container_of(sd, struct ths7303_state, sd);
  64}
  65
  66static int ths7303_read(struct v4l2_subdev *sd, u8 reg)
  67{
  68        struct i2c_client *client = v4l2_get_subdevdata(sd);
  69
  70        return i2c_smbus_read_byte_data(client, reg);
  71}
  72
  73static int ths7303_write(struct v4l2_subdev *sd, u8 reg, u8 val)
  74{
  75        struct i2c_client *client = v4l2_get_subdevdata(sd);
  76        int ret;
  77        int i;
  78
  79        for (i = 0; i < 3; i++) {
  80                ret = i2c_smbus_write_byte_data(client, reg, val);
  81                if (ret == 0)
  82                        return 0;
  83        }
  84        return ret;
  85}
  86
  87/* following function is used to set ths7303 */
  88int ths7303_setval(struct v4l2_subdev *sd, enum ths7303_filter_mode mode)
  89{
  90        struct i2c_client *client = v4l2_get_subdevdata(sd);
  91        struct ths7303_state *state = to_state(sd);
  92        struct ths7303_platform_data *pdata = &state->pdata;
  93        u8 val, sel = 0;
  94        int err, disable = 0;
  95
  96        if (!client)
  97                return -EINVAL;
  98
  99        switch (mode) {
 100        case THS7303_FILTER_MODE_1080P:
 101                sel = 0x3;      /*1080p and SXGA/UXGA */
 102                break;
 103        case THS7303_FILTER_MODE_720P_1080I:
 104                sel = 0x2;      /*720p, 1080i and SVGA/XGA */
 105                break;
 106        case THS7303_FILTER_MODE_480P_576P:
 107                sel = 0x1;      /* EDTV 480p/576p and VGA */
 108                break;
 109        case THS7303_FILTER_MODE_480I_576I:
 110                sel = 0x0;      /* SDTV, S-Video, 480i/576i */
 111                break;
 112        default:
 113                /* disable all channels */
 114                disable = 1;
 115        }
 116
 117        val = (sel << 6) | (sel << 3);
 118        if (!disable)
 119                val |= (pdata->ch_1 & 0x27);
 120        err = ths7303_write(sd, THS7303_CHANNEL_1, val);
 121        if (err)
 122                goto out;
 123
 124        val = (sel << 6) | (sel << 3);
 125        if (!disable)
 126                val |= (pdata->ch_2 & 0x27);
 127        err = ths7303_write(sd, THS7303_CHANNEL_2, val);
 128        if (err)
 129                goto out;
 130
 131        val = (sel << 6) | (sel << 3);
 132        if (!disable)
 133                val |= (pdata->ch_3 & 0x27);
 134        err = ths7303_write(sd, THS7303_CHANNEL_3, val);
 135        if (err)
 136                goto out;
 137
 138        return 0;
 139out:
 140        pr_info("write byte data failed\n");
 141        return err;
 142}
 143
 144static int ths7303_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm)
 145{
 146        struct ths7303_state *state = to_state(sd);
 147
 148        if (norm & (V4L2_STD_ALL & ~V4L2_STD_SECAM)) {
 149                state->std_id = 1;
 150                state->bt.pixelclock = 0;
 151                return ths7303_setval(sd, THS7303_FILTER_MODE_480I_576I);
 152        }
 153
 154        return ths7303_setval(sd, THS7303_FILTER_MODE_DISABLE);
 155}
 156
 157static int ths7303_config(struct v4l2_subdev *sd)
 158{
 159        struct ths7303_state *state = to_state(sd);
 160        int res;
 161
 162        if (!state->stream_on) {
 163                ths7303_write(sd, THS7303_CHANNEL_1,
 164                              (ths7303_read(sd, THS7303_CHANNEL_1) & 0xf8) |
 165                              0x00);
 166                ths7303_write(sd, THS7303_CHANNEL_2,
 167                              (ths7303_read(sd, THS7303_CHANNEL_2) & 0xf8) |
 168                              0x00);
 169                ths7303_write(sd, THS7303_CHANNEL_3,
 170                              (ths7303_read(sd, THS7303_CHANNEL_3) & 0xf8) |
 171                              0x00);
 172                return 0;
 173        }
 174
 175        if (state->bt.pixelclock > 120000000)
 176                res = ths7303_setval(sd, THS7303_FILTER_MODE_1080P);
 177        else if (state->bt.pixelclock > 70000000)
 178                res = ths7303_setval(sd, THS7303_FILTER_MODE_720P_1080I);
 179        else if (state->bt.pixelclock > 20000000)
 180                res = ths7303_setval(sd, THS7303_FILTER_MODE_480P_576P);
 181        else if (state->std_id)
 182                res = ths7303_setval(sd, THS7303_FILTER_MODE_480I_576I);
 183        else
 184                /* disable all channels */
 185                res = ths7303_setval(sd, THS7303_FILTER_MODE_DISABLE);
 186
 187        return res;
 188
 189}
 190
 191static int ths7303_s_stream(struct v4l2_subdev *sd, int enable)
 192{
 193        struct ths7303_state *state = to_state(sd);
 194
 195        state->stream_on = enable;
 196
 197        return ths7303_config(sd);
 198}
 199
 200/* for setting filter for HD output */
 201static int ths7303_s_dv_timings(struct v4l2_subdev *sd,
 202                               struct v4l2_dv_timings *dv_timings)
 203{
 204        struct ths7303_state *state = to_state(sd);
 205
 206        if (!dv_timings || dv_timings->type != V4L2_DV_BT_656_1120)
 207                return -EINVAL;
 208
 209        state->bt = dv_timings->bt;
 210        state->std_id = 0;
 211
 212        return ths7303_config(sd);
 213}
 214
 215static int ths7303_g_chip_ident(struct v4l2_subdev *sd,
 216                                struct v4l2_dbg_chip_ident *chip)
 217{
 218        struct i2c_client *client = v4l2_get_subdevdata(sd);
 219        struct ths7303_state *state = to_state(sd);
 220
 221        return v4l2_chip_ident_i2c_client(client, chip, state->driver_data, 0);
 222}
 223
 224static const struct v4l2_subdev_video_ops ths7303_video_ops = {
 225        .s_stream       = ths7303_s_stream,
 226        .s_std_output   = ths7303_s_std_output,
 227        .s_dv_timings   = ths7303_s_dv_timings,
 228};
 229
 230#ifdef CONFIG_VIDEO_ADV_DEBUG
 231
 232static int ths7303_g_register(struct v4l2_subdev *sd,
 233                              struct v4l2_dbg_register *reg)
 234{
 235        struct i2c_client *client = v4l2_get_subdevdata(sd);
 236
 237        if (!v4l2_chip_match_i2c_client(client, &reg->match))
 238                return -EINVAL;
 239        if (!capable(CAP_SYS_ADMIN))
 240                return -EPERM;
 241
 242        reg->size = 1;
 243        reg->val = ths7303_read(sd, reg->reg);
 244        return 0;
 245}
 246
 247static int ths7303_s_register(struct v4l2_subdev *sd,
 248                              const struct v4l2_dbg_register *reg)
 249{
 250        struct i2c_client *client = v4l2_get_subdevdata(sd);
 251
 252        if (!v4l2_chip_match_i2c_client(client, &reg->match))
 253                return -EINVAL;
 254        if (!capable(CAP_SYS_ADMIN))
 255                return -EPERM;
 256
 257        ths7303_write(sd, reg->reg, reg->val);
 258        return 0;
 259}
 260#endif
 261
 262static const char * const stc_lpf_sel_txt[4] = {
 263        "500-kHz Filter",
 264        "2.5-MHz Filter",
 265        "5-MHz Filter",
 266        "5-MHz Filter",
 267};
 268
 269static const char * const in_mux_sel_txt[2] = {
 270        "Input A Select",
 271        "Input B Select",
 272};
 273
 274static const char * const lpf_freq_sel_txt[4] = {
 275        "9-MHz LPF",
 276        "16-MHz LPF",
 277        "35-MHz LPF",
 278        "Bypass LPF",
 279};
 280
 281static const char * const in_bias_sel_dis_cont_txt[8] = {
 282        "Disable Channel",
 283        "Mute Function - No Output",
 284        "DC Bias Select",
 285        "DC Bias + 250 mV Offset Select",
 286        "AC Bias Select",
 287        "Sync Tip Clamp with low bias",
 288        "Sync Tip Clamp with mid bias",
 289        "Sync Tip Clamp with high bias",
 290};
 291
 292static void ths7303_log_channel_status(struct v4l2_subdev *sd, u8 reg)
 293{
 294        u8 val = ths7303_read(sd, reg);
 295
 296        if ((val & 0x7) == 0) {
 297                v4l2_info(sd, "Channel %d Off\n", reg);
 298                return;
 299        }
 300
 301        v4l2_info(sd, "Channel %d On\n", reg);
 302        v4l2_info(sd, "  value 0x%x\n", val);
 303        v4l2_info(sd, "  %s\n", stc_lpf_sel_txt[(val >> 6) & 0x3]);
 304        v4l2_info(sd, "  %s\n", in_mux_sel_txt[(val >> 5) & 0x1]);
 305        v4l2_info(sd, "  %s\n", lpf_freq_sel_txt[(val >> 3) & 0x3]);
 306        v4l2_info(sd, "  %s\n", in_bias_sel_dis_cont_txt[(val >> 0) & 0x7]);
 307}
 308
 309static int ths7303_log_status(struct v4l2_subdev *sd)
 310{
 311        struct ths7303_state *state = to_state(sd);
 312
 313        v4l2_info(sd, "stream %s\n", state->stream_on ? "On" : "Off");
 314
 315        if (state->bt.pixelclock) {
 316                struct v4l2_bt_timings *bt = bt = &state->bt;
 317                u32 frame_width, frame_height;
 318
 319                frame_width = bt->width + bt->hfrontporch +
 320                              bt->hsync + bt->hbackporch;
 321                frame_height = bt->height + bt->vfrontporch +
 322                               bt->vsync + bt->vbackporch;
 323                v4l2_info(sd,
 324                          "timings: %dx%d%s%d (%dx%d). Pix freq. = %d Hz. Polarities = 0x%x\n",
 325                          bt->width, bt->height, bt->interlaced ? "i" : "p",
 326                          (frame_height * frame_width) > 0 ?
 327                          (int)bt->pixelclock /
 328                          (frame_height * frame_width) : 0,
 329                          frame_width, frame_height,
 330                          (int)bt->pixelclock, bt->polarities);
 331        } else {
 332                v4l2_info(sd, "no timings set\n");
 333        }
 334
 335        ths7303_log_channel_status(sd, THS7303_CHANNEL_1);
 336        ths7303_log_channel_status(sd, THS7303_CHANNEL_2);
 337        ths7303_log_channel_status(sd, THS7303_CHANNEL_3);
 338
 339        return 0;
 340}
 341
 342static const struct v4l2_subdev_core_ops ths7303_core_ops = {
 343        .g_chip_ident = ths7303_g_chip_ident,
 344        .log_status = ths7303_log_status,
 345#ifdef CONFIG_VIDEO_ADV_DEBUG
 346        .g_register = ths7303_g_register,
 347        .s_register = ths7303_s_register,
 348#endif
 349};
 350
 351static const struct v4l2_subdev_ops ths7303_ops = {
 352        .core   = &ths7303_core_ops,
 353        .video  = &ths7303_video_ops,
 354};
 355
 356static int ths7303_setup(struct v4l2_subdev *sd)
 357{
 358        struct ths7303_state *state = to_state(sd);
 359        struct ths7303_platform_data *pdata = &state->pdata;
 360        int ret;
 361        u8 mask;
 362
 363        state->stream_on = pdata->init_enable;
 364
 365        mask = state->stream_on ? 0xff : 0xf8;
 366
 367        ret = ths7303_write(sd, THS7303_CHANNEL_1, pdata->ch_1 & mask);
 368        if (ret)
 369                return ret;
 370
 371        ret = ths7303_write(sd, THS7303_CHANNEL_2, pdata->ch_2 & mask);
 372        if (ret)
 373                return ret;
 374
 375        ret = ths7303_write(sd, THS7303_CHANNEL_3, pdata->ch_3 & mask);
 376        if (ret)
 377                return ret;
 378
 379        return 0;
 380}
 381
 382static int ths7303_probe(struct i2c_client *client,
 383                        const struct i2c_device_id *id)
 384{
 385        struct ths7303_platform_data *pdata = client->dev.platform_data;
 386        struct ths7303_state *state;
 387        struct v4l2_subdev *sd;
 388
 389        if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 390                return -ENODEV;
 391
 392        v4l_info(client, "chip found @ 0x%x (%s)\n",
 393                        client->addr << 1, client->adapter->name);
 394
 395        state = devm_kzalloc(&client->dev, sizeof(struct ths7303_state),
 396                             GFP_KERNEL);
 397        if (!state)
 398                return -ENOMEM;
 399
 400        if (!pdata)
 401                v4l_warn(client, "No platform data, using default data!\n");
 402        else
 403                state->pdata = *pdata;
 404
 405        sd = &state->sd;
 406        v4l2_i2c_subdev_init(sd, client, &ths7303_ops);
 407
 408        /* store the driver data to differntiate the chip */
 409        state->driver_data = (int)id->driver_data;
 410
 411        if (ths7303_setup(sd) < 0) {
 412                v4l_err(client, "init failed\n");
 413                return -EIO;
 414        }
 415
 416        return 0;
 417}
 418
 419static int ths7303_remove(struct i2c_client *client)
 420{
 421        struct v4l2_subdev *sd = i2c_get_clientdata(client);
 422
 423        v4l2_device_unregister_subdev(sd);
 424
 425        return 0;
 426}
 427
 428static const struct i2c_device_id ths7303_id[] = {
 429        {"ths7303", V4L2_IDENT_THS7303},
 430        {"ths7353", V4L2_IDENT_THS7353},
 431        {},
 432};
 433
 434MODULE_DEVICE_TABLE(i2c, ths7303_id);
 435
 436static struct i2c_driver ths7303_driver = {
 437        .driver = {
 438                .owner  = THIS_MODULE,
 439                .name   = "ths73x3",
 440        },
 441        .probe          = ths7303_probe,
 442        .remove         = ths7303_remove,
 443        .id_table       = ths7303_id,
 444};
 445
 446module_i2c_driver(ths7303_driver);
 447