exynos_drm_mic.c (11179B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (C) 2015 Samsung Electronics Co.Ltd 4 * Authors: 5 * Hyungwon Hwang <human.hwang@samsung.com> 6 */ 7 8#include <linux/clk.h> 9#include <linux/component.h> 10#include <linux/delay.h> 11#include <linux/mfd/syscon.h> 12#include <linux/module.h> 13#include <linux/mutex.h> 14#include <linux/of.h> 15#include <linux/of_address.h> 16#include <linux/of_graph.h> 17#include <linux/platform_device.h> 18#include <linux/pm_runtime.h> 19#include <linux/regmap.h> 20 21#include <video/of_videomode.h> 22#include <video/videomode.h> 23 24#include <drm/drm_bridge.h> 25#include <drm/drm_encoder.h> 26#include <drm/drm_print.h> 27 28#include "exynos_drm_drv.h" 29#include "exynos_drm_crtc.h" 30 31/* Sysreg registers for MIC */ 32#define DSD_CFG_MUX 0x1004 33#define MIC0_RGB_MUX (1 << 0) 34#define MIC0_I80_MUX (1 << 1) 35#define MIC0_ON_MUX (1 << 5) 36 37/* MIC registers */ 38#define MIC_OP 0x0 39#define MIC_IP_VER 0x0004 40#define MIC_V_TIMING_0 0x0008 41#define MIC_V_TIMING_1 0x000C 42#define MIC_IMG_SIZE 0x0010 43#define MIC_INPUT_TIMING_0 0x0014 44#define MIC_INPUT_TIMING_1 0x0018 45#define MIC_2D_OUTPUT_TIMING_0 0x001C 46#define MIC_2D_OUTPUT_TIMING_1 0x0020 47#define MIC_2D_OUTPUT_TIMING_2 0x0024 48#define MIC_3D_OUTPUT_TIMING_0 0x0028 49#define MIC_3D_OUTPUT_TIMING_1 0x002C 50#define MIC_3D_OUTPUT_TIMING_2 0x0030 51#define MIC_CORE_PARA_0 0x0034 52#define MIC_CORE_PARA_1 0x0038 53#define MIC_CTC_CTRL 0x0040 54#define MIC_RD_DATA 0x0044 55 56#define MIC_UPD_REG (1 << 31) 57#define MIC_ON_REG (1 << 30) 58#define MIC_TD_ON_REG (1 << 29) 59#define MIC_BS_CHG_OUT (1 << 16) 60#define MIC_VIDEO_TYPE(x) (((x) & 0xf) << 12) 61#define MIC_PSR_EN (1 << 5) 62#define MIC_SW_RST (1 << 4) 63#define MIC_ALL_RST (1 << 3) 64#define MIC_CORE_VER_CONTROL (1 << 2) 65#define MIC_MODE_SEL_COMMAND_MODE (1 << 1) 66#define MIC_MODE_SEL_MASK (1 << 1) 67#define MIC_CORE_EN (1 << 0) 68 69#define MIC_V_PULSE_WIDTH(x) (((x) & 0x3fff) << 16) 70#define MIC_V_PERIOD_LINE(x) ((x) & 0x3fff) 71 72#define MIC_VBP_SIZE(x) (((x) & 0x3fff) << 16) 73#define MIC_VFP_SIZE(x) ((x) & 0x3fff) 74 75#define MIC_IMG_V_SIZE(x) (((x) & 0x3fff) << 16) 76#define MIC_IMG_H_SIZE(x) ((x) & 0x3fff) 77 78#define MIC_H_PULSE_WIDTH_IN(x) (((x) & 0x3fff) << 16) 79#define MIC_H_PERIOD_PIXEL_IN(x) ((x) & 0x3fff) 80 81#define MIC_HBP_SIZE_IN(x) (((x) & 0x3fff) << 16) 82#define MIC_HFP_SIZE_IN(x) ((x) & 0x3fff) 83 84#define MIC_H_PULSE_WIDTH_2D(x) (((x) & 0x3fff) << 16) 85#define MIC_H_PERIOD_PIXEL_2D(x) ((x) & 0x3fff) 86 87#define MIC_HBP_SIZE_2D(x) (((x) & 0x3fff) << 16) 88#define MIC_HFP_SIZE_2D(x) ((x) & 0x3fff) 89 90#define MIC_BS_SIZE_2D(x) ((x) & 0x3fff) 91 92static const char *const clk_names[] = { "pclk_mic0", "sclk_rgb_vclk_to_mic0" }; 93#define NUM_CLKS ARRAY_SIZE(clk_names) 94static DEFINE_MUTEX(mic_mutex); 95 96struct exynos_mic { 97 struct device *dev; 98 void __iomem *reg; 99 struct regmap *sysreg; 100 struct clk *clks[NUM_CLKS]; 101 102 bool i80_mode; 103 struct videomode vm; 104 struct drm_bridge bridge; 105 106 bool enabled; 107}; 108 109static void mic_set_path(struct exynos_mic *mic, bool enable) 110{ 111 int ret; 112 unsigned int val; 113 114 ret = regmap_read(mic->sysreg, DSD_CFG_MUX, &val); 115 if (ret) { 116 DRM_DEV_ERROR(mic->dev, 117 "mic: Failed to read system register\n"); 118 return; 119 } 120 121 if (enable) { 122 if (mic->i80_mode) 123 val |= MIC0_I80_MUX; 124 else 125 val |= MIC0_RGB_MUX; 126 127 val |= MIC0_ON_MUX; 128 } else 129 val &= ~(MIC0_RGB_MUX | MIC0_I80_MUX | MIC0_ON_MUX); 130 131 ret = regmap_write(mic->sysreg, DSD_CFG_MUX, val); 132 if (ret) 133 DRM_DEV_ERROR(mic->dev, 134 "mic: Failed to read system register\n"); 135} 136 137static int mic_sw_reset(struct exynos_mic *mic) 138{ 139 unsigned int retry = 100; 140 int ret; 141 142 writel(MIC_SW_RST, mic->reg + MIC_OP); 143 144 while (retry-- > 0) { 145 ret = readl(mic->reg + MIC_OP); 146 if (!(ret & MIC_SW_RST)) 147 return 0; 148 149 udelay(10); 150 } 151 152 return -ETIMEDOUT; 153} 154 155static void mic_set_porch_timing(struct exynos_mic *mic) 156{ 157 struct videomode vm = mic->vm; 158 u32 reg; 159 160 reg = MIC_V_PULSE_WIDTH(vm.vsync_len) + 161 MIC_V_PERIOD_LINE(vm.vsync_len + vm.vactive + 162 vm.vback_porch + vm.vfront_porch); 163 writel(reg, mic->reg + MIC_V_TIMING_0); 164 165 reg = MIC_VBP_SIZE(vm.vback_porch) + 166 MIC_VFP_SIZE(vm.vfront_porch); 167 writel(reg, mic->reg + MIC_V_TIMING_1); 168 169 reg = MIC_V_PULSE_WIDTH(vm.hsync_len) + 170 MIC_V_PERIOD_LINE(vm.hsync_len + vm.hactive + 171 vm.hback_porch + vm.hfront_porch); 172 writel(reg, mic->reg + MIC_INPUT_TIMING_0); 173 174 reg = MIC_VBP_SIZE(vm.hback_porch) + 175 MIC_VFP_SIZE(vm.hfront_porch); 176 writel(reg, mic->reg + MIC_INPUT_TIMING_1); 177} 178 179static void mic_set_img_size(struct exynos_mic *mic) 180{ 181 struct videomode *vm = &mic->vm; 182 u32 reg; 183 184 reg = MIC_IMG_H_SIZE(vm->hactive) + 185 MIC_IMG_V_SIZE(vm->vactive); 186 187 writel(reg, mic->reg + MIC_IMG_SIZE); 188} 189 190static void mic_set_output_timing(struct exynos_mic *mic) 191{ 192 struct videomode vm = mic->vm; 193 u32 reg, bs_size_2d; 194 195 DRM_DEV_DEBUG(mic->dev, "w: %u, h: %u\n", vm.hactive, vm.vactive); 196 bs_size_2d = ((vm.hactive >> 2) << 1) + (vm.vactive % 4); 197 reg = MIC_BS_SIZE_2D(bs_size_2d); 198 writel(reg, mic->reg + MIC_2D_OUTPUT_TIMING_2); 199 200 if (!mic->i80_mode) { 201 reg = MIC_H_PULSE_WIDTH_2D(vm.hsync_len) + 202 MIC_H_PERIOD_PIXEL_2D(vm.hsync_len + bs_size_2d + 203 vm.hback_porch + vm.hfront_porch); 204 writel(reg, mic->reg + MIC_2D_OUTPUT_TIMING_0); 205 206 reg = MIC_HBP_SIZE_2D(vm.hback_porch) + 207 MIC_H_PERIOD_PIXEL_2D(vm.hfront_porch); 208 writel(reg, mic->reg + MIC_2D_OUTPUT_TIMING_1); 209 } 210} 211 212static void mic_set_reg_on(struct exynos_mic *mic, bool enable) 213{ 214 u32 reg = readl(mic->reg + MIC_OP); 215 216 if (enable) { 217 reg &= ~(MIC_MODE_SEL_MASK | MIC_CORE_VER_CONTROL | MIC_PSR_EN); 218 reg |= (MIC_CORE_EN | MIC_BS_CHG_OUT | MIC_ON_REG); 219 220 reg &= ~MIC_MODE_SEL_COMMAND_MODE; 221 if (mic->i80_mode) 222 reg |= MIC_MODE_SEL_COMMAND_MODE; 223 } else { 224 reg &= ~MIC_CORE_EN; 225 } 226 227 reg |= MIC_UPD_REG; 228 writel(reg, mic->reg + MIC_OP); 229} 230 231static void mic_post_disable(struct drm_bridge *bridge) 232{ 233 struct exynos_mic *mic = bridge->driver_private; 234 235 mutex_lock(&mic_mutex); 236 if (!mic->enabled) 237 goto already_disabled; 238 239 mic_set_path(mic, 0); 240 241 pm_runtime_put(mic->dev); 242 mic->enabled = 0; 243 244already_disabled: 245 mutex_unlock(&mic_mutex); 246} 247 248static void mic_mode_set(struct drm_bridge *bridge, 249 const struct drm_display_mode *mode, 250 const struct drm_display_mode *adjusted_mode) 251{ 252 struct exynos_mic *mic = bridge->driver_private; 253 254 mutex_lock(&mic_mutex); 255 drm_display_mode_to_videomode(mode, &mic->vm); 256 mic->i80_mode = to_exynos_crtc(bridge->encoder->crtc)->i80_mode; 257 mutex_unlock(&mic_mutex); 258} 259 260static void mic_pre_enable(struct drm_bridge *bridge) 261{ 262 struct exynos_mic *mic = bridge->driver_private; 263 int ret; 264 265 mutex_lock(&mic_mutex); 266 if (mic->enabled) 267 goto unlock; 268 269 ret = pm_runtime_resume_and_get(mic->dev); 270 if (ret < 0) 271 goto unlock; 272 273 mic_set_path(mic, 1); 274 275 ret = mic_sw_reset(mic); 276 if (ret) { 277 DRM_DEV_ERROR(mic->dev, "Failed to reset\n"); 278 goto turn_off; 279 } 280 281 if (!mic->i80_mode) 282 mic_set_porch_timing(mic); 283 mic_set_img_size(mic); 284 mic_set_output_timing(mic); 285 mic_set_reg_on(mic, 1); 286 mic->enabled = 1; 287 mutex_unlock(&mic_mutex); 288 289 return; 290 291turn_off: 292 pm_runtime_put(mic->dev); 293unlock: 294 mutex_unlock(&mic_mutex); 295} 296 297static const struct drm_bridge_funcs mic_bridge_funcs = { 298 .post_disable = mic_post_disable, 299 .mode_set = mic_mode_set, 300 .pre_enable = mic_pre_enable, 301}; 302 303static int exynos_mic_bind(struct device *dev, struct device *master, 304 void *data) 305{ 306 struct exynos_mic *mic = dev_get_drvdata(dev); 307 struct drm_device *drm_dev = data; 308 struct exynos_drm_crtc *crtc = exynos_drm_crtc_get_by_type(drm_dev, 309 EXYNOS_DISPLAY_TYPE_LCD); 310 struct drm_encoder *e, *encoder = NULL; 311 312 drm_for_each_encoder(e, drm_dev) 313 if (e->possible_crtcs == drm_crtc_mask(&crtc->base)) 314 encoder = e; 315 if (!encoder) 316 return -ENODEV; 317 318 mic->bridge.driver_private = mic; 319 320 return drm_bridge_attach(encoder, &mic->bridge, NULL, 0); 321} 322 323static void exynos_mic_unbind(struct device *dev, struct device *master, 324 void *data) 325{ 326 struct exynos_mic *mic = dev_get_drvdata(dev); 327 328 mutex_lock(&mic_mutex); 329 if (!mic->enabled) 330 goto already_disabled; 331 332 pm_runtime_put(mic->dev); 333 334already_disabled: 335 mutex_unlock(&mic_mutex); 336} 337 338static const struct component_ops exynos_mic_component_ops = { 339 .bind = exynos_mic_bind, 340 .unbind = exynos_mic_unbind, 341}; 342 343#ifdef CONFIG_PM 344static int exynos_mic_suspend(struct device *dev) 345{ 346 struct exynos_mic *mic = dev_get_drvdata(dev); 347 int i; 348 349 for (i = NUM_CLKS - 1; i > -1; i--) 350 clk_disable_unprepare(mic->clks[i]); 351 352 return 0; 353} 354 355static int exynos_mic_resume(struct device *dev) 356{ 357 struct exynos_mic *mic = dev_get_drvdata(dev); 358 int ret, i; 359 360 for (i = 0; i < NUM_CLKS; i++) { 361 ret = clk_prepare_enable(mic->clks[i]); 362 if (ret < 0) { 363 DRM_DEV_ERROR(dev, "Failed to enable clock (%s)\n", 364 clk_names[i]); 365 while (--i > -1) 366 clk_disable_unprepare(mic->clks[i]); 367 return ret; 368 } 369 } 370 return 0; 371} 372#endif 373 374static const struct dev_pm_ops exynos_mic_pm_ops = { 375 SET_RUNTIME_PM_OPS(exynos_mic_suspend, exynos_mic_resume, NULL) 376 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 377 pm_runtime_force_resume) 378}; 379 380static int exynos_mic_probe(struct platform_device *pdev) 381{ 382 struct device *dev = &pdev->dev; 383 struct exynos_mic *mic; 384 struct resource res; 385 int ret, i; 386 387 mic = devm_kzalloc(dev, sizeof(*mic), GFP_KERNEL); 388 if (!mic) { 389 DRM_DEV_ERROR(dev, 390 "mic: Failed to allocate memory for MIC object\n"); 391 ret = -ENOMEM; 392 goto err; 393 } 394 395 mic->dev = dev; 396 397 ret = of_address_to_resource(dev->of_node, 0, &res); 398 if (ret) { 399 DRM_DEV_ERROR(dev, "mic: Failed to get mem region for MIC\n"); 400 goto err; 401 } 402 mic->reg = devm_ioremap(dev, res.start, resource_size(&res)); 403 if (!mic->reg) { 404 DRM_DEV_ERROR(dev, "mic: Failed to remap for MIC\n"); 405 ret = -ENOMEM; 406 goto err; 407 } 408 409 mic->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node, 410 "samsung,disp-syscon"); 411 if (IS_ERR(mic->sysreg)) { 412 DRM_DEV_ERROR(dev, "mic: Failed to get system register.\n"); 413 ret = PTR_ERR(mic->sysreg); 414 goto err; 415 } 416 417 for (i = 0; i < NUM_CLKS; i++) { 418 mic->clks[i] = devm_clk_get(dev, clk_names[i]); 419 if (IS_ERR(mic->clks[i])) { 420 DRM_DEV_ERROR(dev, "mic: Failed to get clock (%s)\n", 421 clk_names[i]); 422 ret = PTR_ERR(mic->clks[i]); 423 goto err; 424 } 425 } 426 427 platform_set_drvdata(pdev, mic); 428 429 mic->bridge.funcs = &mic_bridge_funcs; 430 mic->bridge.of_node = dev->of_node; 431 432 drm_bridge_add(&mic->bridge); 433 434 pm_runtime_enable(dev); 435 436 ret = component_add(dev, &exynos_mic_component_ops); 437 if (ret) 438 goto err_pm; 439 440 DRM_DEV_DEBUG_KMS(dev, "MIC has been probed\n"); 441 442 return 0; 443 444err_pm: 445 pm_runtime_disable(dev); 446err: 447 return ret; 448} 449 450static int exynos_mic_remove(struct platform_device *pdev) 451{ 452 struct exynos_mic *mic = platform_get_drvdata(pdev); 453 454 component_del(&pdev->dev, &exynos_mic_component_ops); 455 pm_runtime_disable(&pdev->dev); 456 457 drm_bridge_remove(&mic->bridge); 458 459 return 0; 460} 461 462static const struct of_device_id exynos_mic_of_match[] = { 463 { .compatible = "samsung,exynos5433-mic" }, 464 { } 465}; 466MODULE_DEVICE_TABLE(of, exynos_mic_of_match); 467 468struct platform_driver mic_driver = { 469 .probe = exynos_mic_probe, 470 .remove = exynos_mic_remove, 471 .driver = { 472 .name = "exynos-mic", 473 .pm = &exynos_mic_pm_ops, 474 .owner = THIS_MODULE, 475 .of_match_table = exynos_mic_of_match, 476 }, 477};