1/* 2 * Samsung Standard Definition Output (SDO) driver 3 * 4 * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. 5 * 6 * Tomasz Stanislawski, <t.stanislaws@samsung.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published 10 * by the Free Software Foundiation. either version 2 of the License, 11 * or (at your option) any later version 12 */ 13 14#include <linux/clk.h> 15#include <linux/delay.h> 16#include <linux/kernel.h> 17#include <linux/module.h> 18#include <linux/interrupt.h> 19#include <linux/io.h> 20#include <linux/irq.h> 21#include <linux/platform_device.h> 22#include <linux/pm_runtime.h> 23#include <linux/regulator/consumer.h> 24#include <linux/slab.h> 25 26#include <media/v4l2-subdev.h> 27 28#include "regs-sdo.h" 29 30MODULE_AUTHOR("Tomasz Stanislawski, <t.stanislaws@samsung.com>"); 31MODULE_DESCRIPTION("Samsung Standard Definition Output (SDO)"); 32MODULE_LICENSE("GPL"); 33 34#define SDO_DEFAULT_STD V4L2_STD_PAL 35 36struct sdo_format { 37 v4l2_std_id id; 38 /* all modes are 720 pixels wide */ 39 unsigned int height; 40 unsigned int cookie; 41}; 42 43struct sdo_device { 44 /** pointer to device parent */ 45 struct device *dev; 46 /** base address of SDO registers */ 47 void __iomem *regs; 48 /** SDO interrupt */ 49 unsigned int irq; 50 /** DAC source clock */ 51 struct clk *sclk_dac; 52 /** DAC clock */ 53 struct clk *dac; 54 /** DAC physical interface */ 55 struct clk *dacphy; 56 /** clock for control of VPLL */ 57 struct clk *fout_vpll; 58 /** vpll rate before sdo stream was on */ 59 unsigned long vpll_rate; 60 /** regulator for SDO IP power */ 61 struct regulator *vdac; 62 /** regulator for SDO plug detection */ 63 struct regulator *vdet; 64 /** subdev used as device interface */ 65 struct v4l2_subdev sd; 66 /** current format */ 67 const struct sdo_format *fmt; 68}; 69 70static inline struct sdo_device *sd_to_sdev(struct v4l2_subdev *sd) 71{ 72 return container_of(sd, struct sdo_device, sd); 73} 74 75static inline 76void sdo_write_mask(struct sdo_device *sdev, u32 reg_id, u32 value, u32 mask) 77{ 78 u32 old = readl(sdev->regs + reg_id); 79 value = (value & mask) | (old & ~mask); 80 writel(value, sdev->regs + reg_id); 81} 82 83static inline 84void sdo_write(struct sdo_device *sdev, u32 reg_id, u32 value) 85{ 86 writel(value, sdev->regs + reg_id); 87} 88 89static inline 90u32 sdo_read(struct sdo_device *sdev, u32 reg_id) 91{ 92 return readl(sdev->regs + reg_id); 93} 94 95static irqreturn_t sdo_irq_handler(int irq, void *dev_data) 96{ 97 struct sdo_device *sdev = dev_data; 98 99 /* clear interrupt */ 100 sdo_write_mask(sdev, SDO_IRQ, ~0, SDO_VSYNC_IRQ_PEND); 101 return IRQ_HANDLED; 102} 103 104static void sdo_reg_debug(struct sdo_device *sdev) 105{ 106#define DBGREG(reg_id) \ 107 dev_info(sdev->dev, #reg_id " = %08x\n", \ 108 sdo_read(sdev, reg_id)) 109 110 DBGREG(SDO_CLKCON); 111 DBGREG(SDO_CONFIG); 112 DBGREG(SDO_VBI); 113 DBGREG(SDO_DAC); 114 DBGREG(SDO_IRQ); 115 DBGREG(SDO_IRQMASK); 116 DBGREG(SDO_VERSION); 117} 118 119static const struct sdo_format sdo_format[] = { 120 { V4L2_STD_PAL_N, .height = 576, .cookie = SDO_PAL_N }, 121 { V4L2_STD_PAL_Nc, .height = 576, .cookie = SDO_PAL_NC }, 122 { V4L2_STD_PAL_M, .height = 480, .cookie = SDO_PAL_M }, 123 { V4L2_STD_PAL_60, .height = 480, .cookie = SDO_PAL_60 }, 124 { V4L2_STD_NTSC_443, .height = 480, .cookie = SDO_NTSC_443 }, 125 { V4L2_STD_PAL, .height = 576, .cookie = SDO_PAL_BGHID }, 126 { V4L2_STD_NTSC_M, .height = 480, .cookie = SDO_NTSC_M }, 127}; 128 129static const struct sdo_format *sdo_find_format(v4l2_std_id id) 130{ 131 int i; 132 for (i = 0; i < ARRAY_SIZE(sdo_format); ++i) 133 if (sdo_format[i].id & id) 134 return &sdo_format[i]; 135 return NULL; 136} 137 138static int sdo_g_tvnorms_output(struct v4l2_subdev *sd, v4l2_std_id *std) 139{ 140 *std = V4L2_STD_NTSC_M | V4L2_STD_PAL_M | V4L2_STD_PAL | 141 V4L2_STD_PAL_N | V4L2_STD_PAL_Nc | 142 V4L2_STD_NTSC_443 | V4L2_STD_PAL_60; 143 return 0; 144} 145 146static int sdo_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) 147{ 148 struct sdo_device *sdev = sd_to_sdev(sd); 149 const struct sdo_format *fmt; 150 fmt = sdo_find_format(std); 151 if (fmt == NULL) 152 return -EINVAL; 153 sdev->fmt = fmt; 154 return 0; 155} 156 157static int sdo_g_std_output(struct v4l2_subdev *sd, v4l2_std_id *std) 158{ 159 *std = sd_to_sdev(sd)->fmt->id; 160 return 0; 161} 162 163static int sdo_g_mbus_fmt(struct v4l2_subdev *sd, 164 struct v4l2_mbus_framefmt *fmt) 165{ 166 struct sdo_device *sdev = sd_to_sdev(sd); 167 168 if (!sdev->fmt) 169 return -ENXIO; 170 /* all modes are 720 pixels wide */ 171 fmt->width = 720; 172 fmt->height = sdev->fmt->height; 173 fmt->code = MEDIA_BUS_FMT_FIXED; 174 fmt->field = V4L2_FIELD_INTERLACED; 175 fmt->colorspace = V4L2_COLORSPACE_JPEG; 176 return 0; 177} 178 179static int sdo_s_power(struct v4l2_subdev *sd, int on) 180{ 181 struct sdo_device *sdev = sd_to_sdev(sd); 182 struct device *dev = sdev->dev; 183 int ret; 184 185 dev_info(dev, "sdo_s_power(%d)\n", on); 186 187 if (on) 188 ret = pm_runtime_get_sync(dev); 189 else 190 ret = pm_runtime_put_sync(dev); 191 192 /* only values < 0 indicate errors */ 193 return ret < 0 ? ret : 0; 194} 195 196static int sdo_streamon(struct sdo_device *sdev) 197{ 198 int ret; 199 200 /* set proper clock for Timing Generator */ 201 sdev->vpll_rate = clk_get_rate(sdev->fout_vpll); 202 ret = clk_set_rate(sdev->fout_vpll, 54000000); 203 if (ret < 0) { 204 dev_err(sdev->dev, "Failed to set vpll rate\n"); 205 return ret; 206 } 207 dev_info(sdev->dev, "fout_vpll.rate = %lu\n", 208 clk_get_rate(sdev->fout_vpll)); 209 /* enable clock in SDO */ 210 sdo_write_mask(sdev, SDO_CLKCON, ~0, SDO_TVOUT_CLOCK_ON); 211 ret = clk_prepare_enable(sdev->dacphy); 212 if (ret < 0) { 213 dev_err(sdev->dev, "clk_prepare_enable(dacphy) failed\n"); 214 goto fail; 215 } 216 /* enable DAC */ 217 sdo_write_mask(sdev, SDO_DAC, ~0, SDO_POWER_ON_DAC); 218 sdo_reg_debug(sdev); 219 return 0; 220 221fail: 222 sdo_write_mask(sdev, SDO_CLKCON, 0, SDO_TVOUT_CLOCK_ON); 223 clk_set_rate(sdev->fout_vpll, sdev->vpll_rate); 224 return ret; 225} 226 227static int sdo_streamoff(struct sdo_device *sdev) 228{ 229 int tries; 230 231 sdo_write_mask(sdev, SDO_DAC, 0, SDO_POWER_ON_DAC); 232 clk_disable_unprepare(sdev->dacphy); 233 sdo_write_mask(sdev, SDO_CLKCON, 0, SDO_TVOUT_CLOCK_ON); 234 for (tries = 100; tries; --tries) { 235 if (sdo_read(sdev, SDO_CLKCON) & SDO_TVOUT_CLOCK_READY) 236 break; 237 mdelay(1); 238 } 239 if (tries == 0) 240 dev_err(sdev->dev, "failed to stop streaming\n"); 241 clk_set_rate(sdev->fout_vpll, sdev->vpll_rate); 242 return tries ? 0 : -EIO; 243} 244 245static int sdo_s_stream(struct v4l2_subdev *sd, int on) 246{ 247 struct sdo_device *sdev = sd_to_sdev(sd); 248 return on ? sdo_streamon(sdev) : sdo_streamoff(sdev); 249} 250 251static const struct v4l2_subdev_core_ops sdo_sd_core_ops = { 252 .s_power = sdo_s_power, 253}; 254 255static const struct v4l2_subdev_video_ops sdo_sd_video_ops = { 256 .s_std_output = sdo_s_std_output, 257 .g_std_output = sdo_g_std_output, 258 .g_tvnorms_output = sdo_g_tvnorms_output, 259 .g_mbus_fmt = sdo_g_mbus_fmt, 260 .s_stream = sdo_s_stream, 261}; 262 263static const struct v4l2_subdev_ops sdo_sd_ops = { 264 .core = &sdo_sd_core_ops, 265 .video = &sdo_sd_video_ops, 266}; 267 268static int sdo_runtime_suspend(struct device *dev) 269{ 270 struct v4l2_subdev *sd = dev_get_drvdata(dev); 271 struct sdo_device *sdev = sd_to_sdev(sd); 272 273 dev_info(dev, "suspend\n"); 274 regulator_disable(sdev->vdet); 275 regulator_disable(sdev->vdac); 276 clk_disable_unprepare(sdev->sclk_dac); 277 return 0; 278} 279 280static int sdo_runtime_resume(struct device *dev) 281{ 282 struct v4l2_subdev *sd = dev_get_drvdata(dev); 283 struct sdo_device *sdev = sd_to_sdev(sd); 284 int ret; 285 286 dev_info(dev, "resume\n"); 287 288 ret = clk_prepare_enable(sdev->sclk_dac); 289 if (ret < 0) 290 return ret; 291 292 ret = regulator_enable(sdev->vdac); 293 if (ret < 0) 294 goto dac_clk_dis; 295 296 ret = regulator_enable(sdev->vdet); 297 if (ret < 0) 298 goto vdac_r_dis; 299 300 /* software reset */ 301 sdo_write_mask(sdev, SDO_CLKCON, ~0, SDO_TVOUT_SW_RESET); 302 mdelay(10); 303 sdo_write_mask(sdev, SDO_CLKCON, 0, SDO_TVOUT_SW_RESET); 304 305 /* setting TV mode */ 306 sdo_write_mask(sdev, SDO_CONFIG, sdev->fmt->cookie, SDO_STANDARD_MASK); 307 /* XXX: forcing interlaced mode using undocumented bit */ 308 sdo_write_mask(sdev, SDO_CONFIG, 0, SDO_PROGRESSIVE); 309 /* turn all VBI off */ 310 sdo_write_mask(sdev, SDO_VBI, 0, SDO_CVBS_WSS_INS | 311 SDO_CVBS_CLOSED_CAPTION_MASK); 312 /* turn all post processing off */ 313 sdo_write_mask(sdev, SDO_CCCON, ~0, SDO_COMPENSATION_BHS_ADJ_OFF | 314 SDO_COMPENSATION_CVBS_COMP_OFF); 315 sdo_reg_debug(sdev); 316 return 0; 317 318vdac_r_dis: 319 regulator_disable(sdev->vdac); 320dac_clk_dis: 321 clk_disable_unprepare(sdev->sclk_dac); 322 return ret; 323} 324 325static const struct dev_pm_ops sdo_pm_ops = { 326 .runtime_suspend = sdo_runtime_suspend, 327 .runtime_resume = sdo_runtime_resume, 328}; 329 330static int sdo_probe(struct platform_device *pdev) 331{ 332 struct device *dev = &pdev->dev; 333 struct sdo_device *sdev; 334 struct resource *res; 335 int ret = 0; 336 struct clk *sclk_vpll; 337 338 dev_info(dev, "probe start\n"); 339 sdev = devm_kzalloc(&pdev->dev, sizeof(*sdev), GFP_KERNEL); 340 if (!sdev) { 341 dev_err(dev, "not enough memory.\n"); 342 ret = -ENOMEM; 343 goto fail; 344 } 345 sdev->dev = dev; 346 347 /* mapping registers */ 348 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 349 if (res == NULL) { 350 dev_err(dev, "get memory resource failed.\n"); 351 ret = -ENXIO; 352 goto fail; 353 } 354 355 sdev->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); 356 if (sdev->regs == NULL) { 357 dev_err(dev, "register mapping failed.\n"); 358 ret = -ENXIO; 359 goto fail; 360 } 361 362 /* acquiring interrupt */ 363 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 364 if (res == NULL) { 365 dev_err(dev, "get interrupt resource failed.\n"); 366 ret = -ENXIO; 367 goto fail; 368 } 369 ret = devm_request_irq(&pdev->dev, res->start, sdo_irq_handler, 0, 370 "s5p-sdo", sdev); 371 if (ret) { 372 dev_err(dev, "request interrupt failed.\n"); 373 goto fail; 374 } 375 sdev->irq = res->start; 376 377 /* acquire clocks */ 378 sdev->sclk_dac = clk_get(dev, "sclk_dac"); 379 if (IS_ERR(sdev->sclk_dac)) { 380 dev_err(dev, "failed to get clock 'sclk_dac'\n"); 381 ret = PTR_ERR(sdev->sclk_dac); 382 goto fail; 383 } 384 sdev->dac = clk_get(dev, "dac"); 385 if (IS_ERR(sdev->dac)) { 386 dev_err(dev, "failed to get clock 'dac'\n"); 387 ret = PTR_ERR(sdev->dac); 388 goto fail_sclk_dac; 389 } 390 sdev->dacphy = clk_get(dev, "dacphy"); 391 if (IS_ERR(sdev->dacphy)) { 392 dev_err(dev, "failed to get clock 'dacphy'\n"); 393 ret = PTR_ERR(sdev->dacphy); 394 goto fail_dac; 395 } 396 sclk_vpll = clk_get(dev, "sclk_vpll"); 397 if (IS_ERR(sclk_vpll)) { 398 dev_err(dev, "failed to get clock 'sclk_vpll'\n"); 399 ret = PTR_ERR(sclk_vpll); 400 goto fail_dacphy; 401 } 402 clk_set_parent(sdev->sclk_dac, sclk_vpll); 403 clk_put(sclk_vpll); 404 sdev->fout_vpll = clk_get(dev, "fout_vpll"); 405 if (IS_ERR(sdev->fout_vpll)) { 406 dev_err(dev, "failed to get clock 'fout_vpll'\n"); 407 ret = PTR_ERR(sdev->fout_vpll); 408 goto fail_dacphy; 409 } 410 dev_info(dev, "fout_vpll.rate = %lu\n", clk_get_rate(sclk_vpll)); 411 412 /* acquire regulator */ 413 sdev->vdac = devm_regulator_get(dev, "vdd33a_dac"); 414 if (IS_ERR(sdev->vdac)) { 415 dev_err(dev, "failed to get regulator 'vdac'\n"); 416 ret = PTR_ERR(sdev->vdac); 417 goto fail_fout_vpll; 418 } 419 sdev->vdet = devm_regulator_get(dev, "vdet"); 420 if (IS_ERR(sdev->vdet)) { 421 dev_err(dev, "failed to get regulator 'vdet'\n"); 422 ret = PTR_ERR(sdev->vdet); 423 goto fail_fout_vpll; 424 } 425 426 /* enable gate for dac clock, because mixer uses it */ 427 ret = clk_prepare_enable(sdev->dac); 428 if (ret < 0) { 429 dev_err(dev, "clk_prepare_enable(dac) failed\n"); 430 goto fail_fout_vpll; 431 } 432 433 /* configure power management */ 434 pm_runtime_enable(dev); 435 436 /* configuration of interface subdevice */ 437 v4l2_subdev_init(&sdev->sd, &sdo_sd_ops); 438 sdev->sd.owner = THIS_MODULE; 439 strlcpy(sdev->sd.name, "s5p-sdo", sizeof(sdev->sd.name)); 440 441 /* set default format */ 442 sdev->fmt = sdo_find_format(SDO_DEFAULT_STD); 443 BUG_ON(sdev->fmt == NULL); 444 445 /* keeping subdev in device's private for use by other drivers */ 446 dev_set_drvdata(dev, &sdev->sd); 447 448 dev_info(dev, "probe succeeded\n"); 449 return 0; 450 451fail_fout_vpll: 452 clk_put(sdev->fout_vpll); 453fail_dacphy: 454 clk_put(sdev->dacphy); 455fail_dac: 456 clk_put(sdev->dac); 457fail_sclk_dac: 458 clk_put(sdev->sclk_dac); 459fail: 460 dev_info(dev, "probe failed\n"); 461 return ret; 462} 463 464static int sdo_remove(struct platform_device *pdev) 465{ 466 struct v4l2_subdev *sd = dev_get_drvdata(&pdev->dev); 467 struct sdo_device *sdev = sd_to_sdev(sd); 468 469 pm_runtime_disable(&pdev->dev); 470 clk_disable_unprepare(sdev->dac); 471 clk_put(sdev->fout_vpll); 472 clk_put(sdev->dacphy); 473 clk_put(sdev->dac); 474 clk_put(sdev->sclk_dac); 475 476 dev_info(&pdev->dev, "remove successful\n"); 477 return 0; 478} 479 480static struct platform_driver sdo_driver __refdata = { 481 .probe = sdo_probe, 482 .remove = sdo_remove, 483 .driver = { 484 .name = "s5p-sdo", 485 .pm = &sdo_pm_ops, 486 } 487}; 488 489module_platform_driver(sdo_driver); 490