root/drivers/media/i2c/ths7303.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. to_state
  2. ths7303_read
  3. ths7303_write
  4. ths7303_setval
  5. ths7303_s_std_output
  6. ths7303_config
  7. ths7303_s_stream
  8. ths7303_s_dv_timings
  9. ths7303_g_register
  10. ths7303_s_register
  11. ths7303_log_channel_status
  12. ths7303_log_status
  13. ths7303_probe
  14. ths7303_remove

   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/i2c/ths7303.h>
  29 #include <media/v4l2-device.h>
  30 
  31 #define THS7303_CHANNEL_1       1
  32 #define THS7303_CHANNEL_2       2
  33 #define THS7303_CHANNEL_3       3
  34 
  35 struct ths7303_state {
  36         struct v4l2_subdev              sd;
  37         const struct ths7303_platform_data *pdata;
  38         struct v4l2_bt_timings          bt;
  39         int std_id;
  40         int stream_on;
  41 };
  42 
  43 enum ths7303_filter_mode {
  44         THS7303_FILTER_MODE_480I_576I,
  45         THS7303_FILTER_MODE_480P_576P,
  46         THS7303_FILTER_MODE_720P_1080I,
  47         THS7303_FILTER_MODE_1080P,
  48         THS7303_FILTER_MODE_DISABLE
  49 };
  50 
  51 MODULE_DESCRIPTION("TI THS7303 video amplifier driver");
  52 MODULE_AUTHOR("Chaithrika U S");
  53 MODULE_LICENSE("GPL");
  54 
  55 static inline struct ths7303_state *to_state(struct v4l2_subdev *sd)
  56 {
  57         return container_of(sd, struct ths7303_state, sd);
  58 }
  59 
  60 static int ths7303_read(struct v4l2_subdev *sd, u8 reg)
  61 {
  62         struct i2c_client *client = v4l2_get_subdevdata(sd);
  63 
  64         return i2c_smbus_read_byte_data(client, reg);
  65 }
  66 
  67 static int ths7303_write(struct v4l2_subdev *sd, u8 reg, u8 val)
  68 {
  69         struct i2c_client *client = v4l2_get_subdevdata(sd);
  70         int ret;
  71         int i;
  72 
  73         for (i = 0; i < 3; i++) {
  74                 ret = i2c_smbus_write_byte_data(client, reg, val);
  75                 if (ret == 0)
  76                         return 0;
  77         }
  78         return ret;
  79 }
  80 
  81 /* following function is used to set ths7303 */
  82 static int ths7303_setval(struct v4l2_subdev *sd,
  83                           enum ths7303_filter_mode mode)
  84 {
  85         struct i2c_client *client = v4l2_get_subdevdata(sd);
  86         struct ths7303_state *state = to_state(sd);
  87         const struct ths7303_platform_data *pdata = state->pdata;
  88         u8 val, sel = 0;
  89         int err, disable = 0;
  90 
  91         if (!client)
  92                 return -EINVAL;
  93 
  94         switch (mode) {
  95         case THS7303_FILTER_MODE_1080P:
  96                 sel = 0x3;      /*1080p and SXGA/UXGA */
  97                 break;
  98         case THS7303_FILTER_MODE_720P_1080I:
  99                 sel = 0x2;      /*720p, 1080i and SVGA/XGA */
 100                 break;
 101         case THS7303_FILTER_MODE_480P_576P:
 102                 sel = 0x1;      /* EDTV 480p/576p and VGA */
 103                 break;
 104         case THS7303_FILTER_MODE_480I_576I:
 105                 sel = 0x0;      /* SDTV, S-Video, 480i/576i */
 106                 break;
 107         default:
 108                 /* disable all channels */
 109                 disable = 1;
 110         }
 111 
 112         val = (sel << 6) | (sel << 3);
 113         if (!disable)
 114                 val |= (pdata->ch_1 & 0x27);
 115         err = ths7303_write(sd, THS7303_CHANNEL_1, val);
 116         if (err)
 117                 goto out;
 118 
 119         val = (sel << 6) | (sel << 3);
 120         if (!disable)
 121                 val |= (pdata->ch_2 & 0x27);
 122         err = ths7303_write(sd, THS7303_CHANNEL_2, val);
 123         if (err)
 124                 goto out;
 125 
 126         val = (sel << 6) | (sel << 3);
 127         if (!disable)
 128                 val |= (pdata->ch_3 & 0x27);
 129         err = ths7303_write(sd, THS7303_CHANNEL_3, val);
 130         if (err)
 131                 goto out;
 132 
 133         return 0;
 134 out:
 135         pr_info("write byte data failed\n");
 136         return err;
 137 }
 138 
 139 static int ths7303_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm)
 140 {
 141         struct ths7303_state *state = to_state(sd);
 142 
 143         if (norm & (V4L2_STD_ALL & ~V4L2_STD_SECAM)) {
 144                 state->std_id = 1;
 145                 state->bt.pixelclock = 0;
 146                 return ths7303_setval(sd, THS7303_FILTER_MODE_480I_576I);
 147         }
 148 
 149         return ths7303_setval(sd, THS7303_FILTER_MODE_DISABLE);
 150 }
 151 
 152 static int ths7303_config(struct v4l2_subdev *sd)
 153 {
 154         struct ths7303_state *state = to_state(sd);
 155         int res;
 156 
 157         if (!state->stream_on) {
 158                 ths7303_write(sd, THS7303_CHANNEL_1,
 159                               (ths7303_read(sd, THS7303_CHANNEL_1) & 0xf8) |
 160                               0x00);
 161                 ths7303_write(sd, THS7303_CHANNEL_2,
 162                               (ths7303_read(sd, THS7303_CHANNEL_2) & 0xf8) |
 163                               0x00);
 164                 ths7303_write(sd, THS7303_CHANNEL_3,
 165                               (ths7303_read(sd, THS7303_CHANNEL_3) & 0xf8) |
 166                               0x00);
 167                 return 0;
 168         }
 169 
 170         if (state->bt.pixelclock > 120000000)
 171                 res = ths7303_setval(sd, THS7303_FILTER_MODE_1080P);
 172         else if (state->bt.pixelclock > 70000000)
 173                 res = ths7303_setval(sd, THS7303_FILTER_MODE_720P_1080I);
 174         else if (state->bt.pixelclock > 20000000)
 175                 res = ths7303_setval(sd, THS7303_FILTER_MODE_480P_576P);
 176         else if (state->std_id)
 177                 res = ths7303_setval(sd, THS7303_FILTER_MODE_480I_576I);
 178         else
 179                 /* disable all channels */
 180                 res = ths7303_setval(sd, THS7303_FILTER_MODE_DISABLE);
 181 
 182         return res;
 183 
 184 }
 185 
 186 static int ths7303_s_stream(struct v4l2_subdev *sd, int enable)
 187 {
 188         struct ths7303_state *state = to_state(sd);
 189 
 190         state->stream_on = enable;
 191 
 192         return ths7303_config(sd);
 193 }
 194 
 195 /* for setting filter for HD output */
 196 static int ths7303_s_dv_timings(struct v4l2_subdev *sd,
 197                                struct v4l2_dv_timings *dv_timings)
 198 {
 199         struct ths7303_state *state = to_state(sd);
 200 
 201         if (!dv_timings || dv_timings->type != V4L2_DV_BT_656_1120)
 202                 return -EINVAL;
 203 
 204         state->bt = dv_timings->bt;
 205         state->std_id = 0;
 206 
 207         return ths7303_config(sd);
 208 }
 209 
 210 static const struct v4l2_subdev_video_ops ths7303_video_ops = {
 211         .s_stream       = ths7303_s_stream,
 212         .s_std_output   = ths7303_s_std_output,
 213         .s_dv_timings   = ths7303_s_dv_timings,
 214 };
 215 
 216 #ifdef CONFIG_VIDEO_ADV_DEBUG
 217 
 218 static int ths7303_g_register(struct v4l2_subdev *sd,
 219                               struct v4l2_dbg_register *reg)
 220 {
 221         reg->size = 1;
 222         reg->val = ths7303_read(sd, reg->reg);
 223         return 0;
 224 }
 225 
 226 static int ths7303_s_register(struct v4l2_subdev *sd,
 227                               const struct v4l2_dbg_register *reg)
 228 {
 229         ths7303_write(sd, reg->reg, reg->val);
 230         return 0;
 231 }
 232 #endif
 233 
 234 static const char * const stc_lpf_sel_txt[4] = {
 235         "500-kHz Filter",
 236         "2.5-MHz Filter",
 237         "5-MHz Filter",
 238         "5-MHz Filter",
 239 };
 240 
 241 static const char * const in_mux_sel_txt[2] = {
 242         "Input A Select",
 243         "Input B Select",
 244 };
 245 
 246 static const char * const lpf_freq_sel_txt[4] = {
 247         "9-MHz LPF",
 248         "16-MHz LPF",
 249         "35-MHz LPF",
 250         "Bypass LPF",
 251 };
 252 
 253 static const char * const in_bias_sel_dis_cont_txt[8] = {
 254         "Disable Channel",
 255         "Mute Function - No Output",
 256         "DC Bias Select",
 257         "DC Bias + 250 mV Offset Select",
 258         "AC Bias Select",
 259         "Sync Tip Clamp with low bias",
 260         "Sync Tip Clamp with mid bias",
 261         "Sync Tip Clamp with high bias",
 262 };
 263 
 264 static void ths7303_log_channel_status(struct v4l2_subdev *sd, u8 reg)
 265 {
 266         u8 val = ths7303_read(sd, reg);
 267 
 268         if ((val & 0x7) == 0) {
 269                 v4l2_info(sd, "Channel %d Off\n", reg);
 270                 return;
 271         }
 272 
 273         v4l2_info(sd, "Channel %d On\n", reg);
 274         v4l2_info(sd, "  value 0x%x\n", val);
 275         v4l2_info(sd, "  %s\n", stc_lpf_sel_txt[(val >> 6) & 0x3]);
 276         v4l2_info(sd, "  %s\n", in_mux_sel_txt[(val >> 5) & 0x1]);
 277         v4l2_info(sd, "  %s\n", lpf_freq_sel_txt[(val >> 3) & 0x3]);
 278         v4l2_info(sd, "  %s\n", in_bias_sel_dis_cont_txt[(val >> 0) & 0x7]);
 279 }
 280 
 281 static int ths7303_log_status(struct v4l2_subdev *sd)
 282 {
 283         struct ths7303_state *state = to_state(sd);
 284 
 285         v4l2_info(sd, "stream %s\n", state->stream_on ? "On" : "Off");
 286 
 287         if (state->bt.pixelclock) {
 288                 struct v4l2_bt_timings *bt = &state->bt;
 289                 u32 frame_width, frame_height;
 290 
 291                 frame_width = V4L2_DV_BT_FRAME_WIDTH(bt);
 292                 frame_height = V4L2_DV_BT_FRAME_HEIGHT(bt);
 293                 v4l2_info(sd,
 294                           "timings: %dx%d%s%d (%dx%d). Pix freq. = %d Hz. Polarities = 0x%x\n",
 295                           bt->width, bt->height, bt->interlaced ? "i" : "p",
 296                           (frame_height * frame_width) > 0 ?
 297                           (int)bt->pixelclock /
 298                           (frame_height * frame_width) : 0,
 299                           frame_width, frame_height,
 300                           (int)bt->pixelclock, bt->polarities);
 301         } else {
 302                 v4l2_info(sd, "no timings set\n");
 303         }
 304 
 305         ths7303_log_channel_status(sd, THS7303_CHANNEL_1);
 306         ths7303_log_channel_status(sd, THS7303_CHANNEL_2);
 307         ths7303_log_channel_status(sd, THS7303_CHANNEL_3);
 308 
 309         return 0;
 310 }
 311 
 312 static const struct v4l2_subdev_core_ops ths7303_core_ops = {
 313         .log_status = ths7303_log_status,
 314 #ifdef CONFIG_VIDEO_ADV_DEBUG
 315         .g_register = ths7303_g_register,
 316         .s_register = ths7303_s_register,
 317 #endif
 318 };
 319 
 320 static const struct v4l2_subdev_ops ths7303_ops = {
 321         .core   = &ths7303_core_ops,
 322         .video  = &ths7303_video_ops,
 323 };
 324 
 325 static int ths7303_probe(struct i2c_client *client,
 326                         const struct i2c_device_id *id)
 327 {
 328         struct ths7303_platform_data *pdata = client->dev.platform_data;
 329         struct ths7303_state *state;
 330         struct v4l2_subdev *sd;
 331 
 332         if (pdata == NULL) {
 333                 dev_err(&client->dev, "No platform data\n");
 334                 return -EINVAL;
 335         }
 336 
 337         if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 338                 return -ENODEV;
 339 
 340         v4l_info(client, "chip found @ 0x%x (%s)\n",
 341                         client->addr << 1, client->adapter->name);
 342 
 343         state = devm_kzalloc(&client->dev, sizeof(struct ths7303_state),
 344                              GFP_KERNEL);
 345         if (!state)
 346                 return -ENOMEM;
 347 
 348         state->pdata = pdata;
 349         sd = &state->sd;
 350         v4l2_i2c_subdev_init(sd, client, &ths7303_ops);
 351 
 352         /* set to default 480I_576I filter mode */
 353         if (ths7303_setval(sd, THS7303_FILTER_MODE_480I_576I) < 0) {
 354                 v4l_err(client, "Setting to 480I_576I filter mode failed!\n");
 355                 return -EINVAL;
 356         }
 357 
 358         return 0;
 359 }
 360 
 361 static int ths7303_remove(struct i2c_client *client)
 362 {
 363         struct v4l2_subdev *sd = i2c_get_clientdata(client);
 364 
 365         v4l2_device_unregister_subdev(sd);
 366 
 367         return 0;
 368 }
 369 
 370 static const struct i2c_device_id ths7303_id[] = {
 371         {"ths7303", 0},
 372         {"ths7353", 0},
 373         {},
 374 };
 375 
 376 MODULE_DEVICE_TABLE(i2c, ths7303_id);
 377 
 378 static struct i2c_driver ths7303_driver = {
 379         .driver = {
 380                 .name   = "ths73x3",
 381         },
 382         .probe          = ths7303_probe,
 383         .remove         = ths7303_remove,
 384         .id_table       = ths7303_id,
 385 };
 386 
 387 module_i2c_driver(ths7303_driver);

/* [<][>][^][v][top][bottom][index][help] */