1/* 2 * Samsung TV Mixer 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 "mixer.h" 15 16#include <linux/module.h> 17#include <linux/platform_device.h> 18#include <linux/io.h> 19#include <linux/interrupt.h> 20#include <linux/irq.h> 21#include <linux/fb.h> 22#include <linux/delay.h> 23#include <linux/pm_runtime.h> 24#include <linux/clk.h> 25 26MODULE_AUTHOR("Tomasz Stanislawski, <t.stanislaws@samsung.com>"); 27MODULE_DESCRIPTION("Samsung MIXER"); 28MODULE_LICENSE("GPL"); 29 30/* --------- DRIVER PARAMETERS ---------- */ 31 32static struct mxr_output_conf mxr_output_conf[] = { 33 { 34 .output_name = "S5P HDMI connector", 35 .module_name = "s5p-hdmi", 36 .cookie = 1, 37 }, 38 { 39 .output_name = "S5P SDO connector", 40 .module_name = "s5p-sdo", 41 .cookie = 0, 42 }, 43}; 44 45void mxr_get_mbus_fmt(struct mxr_device *mdev, 46 struct v4l2_mbus_framefmt *mbus_fmt) 47{ 48 struct v4l2_subdev *sd; 49 int ret; 50 51 mutex_lock(&mdev->mutex); 52 sd = to_outsd(mdev); 53 ret = v4l2_subdev_call(sd, video, g_mbus_fmt, mbus_fmt); 54 WARN(ret, "failed to get mbus_fmt for output %s\n", sd->name); 55 mutex_unlock(&mdev->mutex); 56} 57 58void mxr_streamer_get(struct mxr_device *mdev) 59{ 60 mutex_lock(&mdev->mutex); 61 ++mdev->n_streamer; 62 mxr_dbg(mdev, "%s(%d)\n", __func__, mdev->n_streamer); 63 if (mdev->n_streamer == 1) { 64 struct v4l2_subdev *sd = to_outsd(mdev); 65 struct v4l2_mbus_framefmt mbus_fmt; 66 struct mxr_resources *res = &mdev->res; 67 int ret; 68 69 if (to_output(mdev)->cookie == 0) 70 clk_set_parent(res->sclk_mixer, res->sclk_dac); 71 else 72 clk_set_parent(res->sclk_mixer, res->sclk_hdmi); 73 mxr_reg_s_output(mdev, to_output(mdev)->cookie); 74 75 ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mbus_fmt); 76 WARN(ret, "failed to get mbus_fmt for output %s\n", sd->name); 77 ret = v4l2_subdev_call(sd, video, s_stream, 1); 78 WARN(ret, "starting stream failed for output %s\n", sd->name); 79 80 mxr_reg_set_mbus_fmt(mdev, &mbus_fmt); 81 mxr_reg_streamon(mdev); 82 ret = mxr_reg_wait4vsync(mdev); 83 WARN(ret, "failed to get vsync (%d) from output\n", ret); 84 } 85 mutex_unlock(&mdev->mutex); 86 mxr_reg_dump(mdev); 87 /* FIXME: what to do when streaming fails? */ 88} 89 90void mxr_streamer_put(struct mxr_device *mdev) 91{ 92 mutex_lock(&mdev->mutex); 93 --mdev->n_streamer; 94 mxr_dbg(mdev, "%s(%d)\n", __func__, mdev->n_streamer); 95 if (mdev->n_streamer == 0) { 96 int ret; 97 struct v4l2_subdev *sd = to_outsd(mdev); 98 99 mxr_reg_streamoff(mdev); 100 /* vsync applies Mixer setup */ 101 ret = mxr_reg_wait4vsync(mdev); 102 WARN(ret, "failed to get vsync (%d) from output\n", ret); 103 ret = v4l2_subdev_call(sd, video, s_stream, 0); 104 WARN(ret, "stopping stream failed for output %s\n", sd->name); 105 } 106 WARN(mdev->n_streamer < 0, "negative number of streamers (%d)\n", 107 mdev->n_streamer); 108 mutex_unlock(&mdev->mutex); 109 mxr_reg_dump(mdev); 110} 111 112void mxr_output_get(struct mxr_device *mdev) 113{ 114 mutex_lock(&mdev->mutex); 115 ++mdev->n_output; 116 mxr_dbg(mdev, "%s(%d)\n", __func__, mdev->n_output); 117 /* turn on auxiliary driver */ 118 if (mdev->n_output == 1) 119 v4l2_subdev_call(to_outsd(mdev), core, s_power, 1); 120 mutex_unlock(&mdev->mutex); 121} 122 123void mxr_output_put(struct mxr_device *mdev) 124{ 125 mutex_lock(&mdev->mutex); 126 --mdev->n_output; 127 mxr_dbg(mdev, "%s(%d)\n", __func__, mdev->n_output); 128 /* turn on auxiliary driver */ 129 if (mdev->n_output == 0) 130 v4l2_subdev_call(to_outsd(mdev), core, s_power, 0); 131 WARN(mdev->n_output < 0, "negative number of output users (%d)\n", 132 mdev->n_output); 133 mutex_unlock(&mdev->mutex); 134} 135 136int mxr_power_get(struct mxr_device *mdev) 137{ 138 int ret = pm_runtime_get_sync(mdev->dev); 139 140 /* returning 1 means that power is already enabled, 141 * so zero success be returned */ 142 if (IS_ERR_VALUE(ret)) 143 return ret; 144 return 0; 145} 146 147void mxr_power_put(struct mxr_device *mdev) 148{ 149 pm_runtime_put_sync(mdev->dev); 150} 151 152/* --------- RESOURCE MANAGEMENT -------------*/ 153 154static int mxr_acquire_plat_resources(struct mxr_device *mdev, 155 struct platform_device *pdev) 156{ 157 struct resource *res; 158 int ret; 159 160 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mxr"); 161 if (res == NULL) { 162 mxr_err(mdev, "get memory resource failed.\n"); 163 ret = -ENXIO; 164 goto fail; 165 } 166 167 mdev->res.mxr_regs = ioremap(res->start, resource_size(res)); 168 if (mdev->res.mxr_regs == NULL) { 169 mxr_err(mdev, "register mapping failed.\n"); 170 ret = -ENXIO; 171 goto fail; 172 } 173 174 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vp"); 175 if (res == NULL) { 176 mxr_err(mdev, "get memory resource failed.\n"); 177 ret = -ENXIO; 178 goto fail_mxr_regs; 179 } 180 181 mdev->res.vp_regs = ioremap(res->start, resource_size(res)); 182 if (mdev->res.vp_regs == NULL) { 183 mxr_err(mdev, "register mapping failed.\n"); 184 ret = -ENXIO; 185 goto fail_mxr_regs; 186 } 187 188 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "irq"); 189 if (res == NULL) { 190 mxr_err(mdev, "get interrupt resource failed.\n"); 191 ret = -ENXIO; 192 goto fail_vp_regs; 193 } 194 195 ret = request_irq(res->start, mxr_irq_handler, 0, "s5p-mixer", mdev); 196 if (ret) { 197 mxr_err(mdev, "request interrupt failed.\n"); 198 goto fail_vp_regs; 199 } 200 mdev->res.irq = res->start; 201 202 return 0; 203 204fail_vp_regs: 205 iounmap(mdev->res.vp_regs); 206 207fail_mxr_regs: 208 iounmap(mdev->res.mxr_regs); 209 210fail: 211 return ret; 212} 213 214static void mxr_resource_clear_clocks(struct mxr_resources *res) 215{ 216 res->mixer = ERR_PTR(-EINVAL); 217 res->vp = ERR_PTR(-EINVAL); 218 res->sclk_mixer = ERR_PTR(-EINVAL); 219 res->sclk_hdmi = ERR_PTR(-EINVAL); 220 res->sclk_dac = ERR_PTR(-EINVAL); 221} 222 223static void mxr_release_plat_resources(struct mxr_device *mdev) 224{ 225 free_irq(mdev->res.irq, mdev); 226 iounmap(mdev->res.vp_regs); 227 iounmap(mdev->res.mxr_regs); 228} 229 230static void mxr_release_clocks(struct mxr_device *mdev) 231{ 232 struct mxr_resources *res = &mdev->res; 233 234 if (!IS_ERR(res->sclk_dac)) 235 clk_put(res->sclk_dac); 236 if (!IS_ERR(res->sclk_hdmi)) 237 clk_put(res->sclk_hdmi); 238 if (!IS_ERR(res->sclk_mixer)) 239 clk_put(res->sclk_mixer); 240 if (!IS_ERR(res->vp)) 241 clk_put(res->vp); 242 if (!IS_ERR(res->mixer)) 243 clk_put(res->mixer); 244} 245 246static int mxr_acquire_clocks(struct mxr_device *mdev) 247{ 248 struct mxr_resources *res = &mdev->res; 249 struct device *dev = mdev->dev; 250 251 mxr_resource_clear_clocks(res); 252 253 res->mixer = clk_get(dev, "mixer"); 254 if (IS_ERR(res->mixer)) { 255 mxr_err(mdev, "failed to get clock 'mixer'\n"); 256 goto fail; 257 } 258 res->vp = clk_get(dev, "vp"); 259 if (IS_ERR(res->vp)) { 260 mxr_err(mdev, "failed to get clock 'vp'\n"); 261 goto fail; 262 } 263 res->sclk_mixer = clk_get(dev, "sclk_mixer"); 264 if (IS_ERR(res->sclk_mixer)) { 265 mxr_err(mdev, "failed to get clock 'sclk_mixer'\n"); 266 goto fail; 267 } 268 res->sclk_hdmi = clk_get(dev, "sclk_hdmi"); 269 if (IS_ERR(res->sclk_hdmi)) { 270 mxr_err(mdev, "failed to get clock 'sclk_hdmi'\n"); 271 goto fail; 272 } 273 res->sclk_dac = clk_get(dev, "sclk_dac"); 274 if (IS_ERR(res->sclk_dac)) { 275 mxr_err(mdev, "failed to get clock 'sclk_dac'\n"); 276 goto fail; 277 } 278 279 return 0; 280fail: 281 mxr_release_clocks(mdev); 282 return -ENODEV; 283} 284 285static int mxr_acquire_resources(struct mxr_device *mdev, 286 struct platform_device *pdev) 287{ 288 int ret; 289 ret = mxr_acquire_plat_resources(mdev, pdev); 290 291 if (ret) 292 goto fail; 293 294 ret = mxr_acquire_clocks(mdev); 295 if (ret) 296 goto fail_plat; 297 298 mxr_info(mdev, "resources acquired\n"); 299 return 0; 300 301fail_plat: 302 mxr_release_plat_resources(mdev); 303fail: 304 mxr_err(mdev, "resources acquire failed\n"); 305 return ret; 306} 307 308static void mxr_release_resources(struct mxr_device *mdev) 309{ 310 mxr_release_clocks(mdev); 311 mxr_release_plat_resources(mdev); 312 memset(&mdev->res, 0, sizeof(mdev->res)); 313 mxr_resource_clear_clocks(&mdev->res); 314} 315 316static void mxr_release_layers(struct mxr_device *mdev) 317{ 318 int i; 319 320 for (i = 0; i < ARRAY_SIZE(mdev->layer); ++i) 321 if (mdev->layer[i]) 322 mxr_layer_release(mdev->layer[i]); 323} 324 325static int mxr_acquire_layers(struct mxr_device *mdev, 326 struct mxr_platform_data *pdata) 327{ 328 mdev->layer[0] = mxr_graph_layer_create(mdev, 0); 329 mdev->layer[1] = mxr_graph_layer_create(mdev, 1); 330 mdev->layer[2] = mxr_vp_layer_create(mdev, 0); 331 332 if (!mdev->layer[0] || !mdev->layer[1] || !mdev->layer[2]) { 333 mxr_err(mdev, "failed to acquire layers\n"); 334 goto fail; 335 } 336 337 return 0; 338 339fail: 340 mxr_release_layers(mdev); 341 return -ENODEV; 342} 343 344/* ---------- POWER MANAGEMENT ----------- */ 345 346static int mxr_runtime_resume(struct device *dev) 347{ 348 struct mxr_device *mdev = to_mdev(dev); 349 struct mxr_resources *res = &mdev->res; 350 int ret; 351 352 mxr_dbg(mdev, "resume - start\n"); 353 mutex_lock(&mdev->mutex); 354 /* turn clocks on */ 355 ret = clk_prepare_enable(res->mixer); 356 if (ret < 0) { 357 dev_err(mdev->dev, "clk_prepare_enable(mixer) failed\n"); 358 goto fail; 359 } 360 ret = clk_prepare_enable(res->vp); 361 if (ret < 0) { 362 dev_err(mdev->dev, "clk_prepare_enable(vp) failed\n"); 363 goto fail_mixer; 364 } 365 ret = clk_prepare_enable(res->sclk_mixer); 366 if (ret < 0) { 367 dev_err(mdev->dev, "clk_prepare_enable(sclk_mixer) failed\n"); 368 goto fail_vp; 369 } 370 /* apply default configuration */ 371 mxr_reg_reset(mdev); 372 mxr_dbg(mdev, "resume - finished\n"); 373 374 mutex_unlock(&mdev->mutex); 375 return 0; 376 377fail_vp: 378 clk_disable_unprepare(res->vp); 379fail_mixer: 380 clk_disable_unprepare(res->mixer); 381fail: 382 mutex_unlock(&mdev->mutex); 383 dev_err(mdev->dev, "resume failed\n"); 384 return ret; 385} 386 387static int mxr_runtime_suspend(struct device *dev) 388{ 389 struct mxr_device *mdev = to_mdev(dev); 390 struct mxr_resources *res = &mdev->res; 391 mxr_dbg(mdev, "suspend - start\n"); 392 mutex_lock(&mdev->mutex); 393 /* turn clocks off */ 394 clk_disable_unprepare(res->sclk_mixer); 395 clk_disable_unprepare(res->vp); 396 clk_disable_unprepare(res->mixer); 397 mutex_unlock(&mdev->mutex); 398 mxr_dbg(mdev, "suspend - finished\n"); 399 return 0; 400} 401 402static const struct dev_pm_ops mxr_pm_ops = { 403 .runtime_suspend = mxr_runtime_suspend, 404 .runtime_resume = mxr_runtime_resume, 405}; 406 407/* --------- DRIVER INITIALIZATION ---------- */ 408 409static int mxr_probe(struct platform_device *pdev) 410{ 411 struct device *dev = &pdev->dev; 412 struct mxr_platform_data *pdata = dev->platform_data; 413 struct mxr_device *mdev; 414 int ret; 415 416 /* mdev does not exist yet so no mxr_dbg is used */ 417 dev_info(dev, "probe start\n"); 418 419 mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); 420 if (!mdev) { 421 dev_err(dev, "not enough memory.\n"); 422 ret = -ENOMEM; 423 goto fail; 424 } 425 426 /* setup pointer to master device */ 427 mdev->dev = dev; 428 429 mutex_init(&mdev->mutex); 430 spin_lock_init(&mdev->reg_slock); 431 init_waitqueue_head(&mdev->event_queue); 432 433 /* acquire resources: regs, irqs, clocks, regulators */ 434 ret = mxr_acquire_resources(mdev, pdev); 435 if (ret) 436 goto fail_mem; 437 438 /* configure resources for video output */ 439 ret = mxr_acquire_video(mdev, mxr_output_conf, 440 ARRAY_SIZE(mxr_output_conf)); 441 if (ret) 442 goto fail_resources; 443 444 /* configure layers */ 445 ret = mxr_acquire_layers(mdev, pdata); 446 if (ret) 447 goto fail_video; 448 449 pm_runtime_enable(dev); 450 451 mxr_info(mdev, "probe successful\n"); 452 return 0; 453 454fail_video: 455 mxr_release_video(mdev); 456 457fail_resources: 458 mxr_release_resources(mdev); 459 460fail_mem: 461 kfree(mdev); 462 463fail: 464 dev_info(dev, "probe failed\n"); 465 return ret; 466} 467 468static int mxr_remove(struct platform_device *pdev) 469{ 470 struct device *dev = &pdev->dev; 471 struct mxr_device *mdev = to_mdev(dev); 472 473 pm_runtime_disable(dev); 474 475 mxr_release_layers(mdev); 476 mxr_release_video(mdev); 477 mxr_release_resources(mdev); 478 479 kfree(mdev); 480 481 dev_info(dev, "remove successful\n"); 482 return 0; 483} 484 485static struct platform_driver mxr_driver __refdata = { 486 .probe = mxr_probe, 487 .remove = mxr_remove, 488 .driver = { 489 .name = MXR_DRIVER_NAME, 490 .pm = &mxr_pm_ops, 491 } 492}; 493 494static int __init mxr_init(void) 495{ 496 int i, ret; 497 static const char banner[] __initconst = 498 "Samsung TV Mixer driver, " 499 "(c) 2010-2011 Samsung Electronics Co., Ltd.\n"; 500 pr_info("%s\n", banner); 501 502 /* Loading auxiliary modules */ 503 for (i = 0; i < ARRAY_SIZE(mxr_output_conf); ++i) 504 request_module(mxr_output_conf[i].module_name); 505 506 ret = platform_driver_register(&mxr_driver); 507 if (ret != 0) { 508 pr_err("s5p-tv: registration of MIXER driver failed\n"); 509 return -ENXIO; 510 } 511 512 return 0; 513} 514module_init(mxr_init); 515 516static void __exit mxr_exit(void) 517{ 518 platform_driver_unregister(&mxr_driver); 519} 520module_exit(mxr_exit); 521