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