1 /* 2 * Copyright (C) 2015 Samsung Electronics Co.Ltd 3 * Authors: 4 * Hyungwon Hwang <human.hwang@samsung.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundationr 9 */ 10 11 #include <linux/platform_device.h> 12 #include <video/of_videomode.h> 13 #include <linux/of_address.h> 14 #include <video/videomode.h> 15 #include <linux/module.h> 16 #include <linux/delay.h> 17 #include <linux/mutex.h> 18 #include <linux/of.h> 19 #include <linux/of_graph.h> 20 #include <linux/clk.h> 21 #include <linux/component.h> 22 #include <drm/drmP.h> 23 #include <linux/mfd/syscon.h> 24 #include <linux/regmap.h> 25 26 /* Sysreg registers for MIC */ 27 #define DSD_CFG_MUX 0x1004 28 #define MIC0_RGB_MUX (1 << 0) 29 #define MIC0_I80_MUX (1 << 1) 30 #define MIC0_ON_MUX (1 << 5) 31 32 /* MIC registers */ 33 #define MIC_OP 0x0 34 #define MIC_IP_VER 0x0004 35 #define MIC_V_TIMING_0 0x0008 36 #define MIC_V_TIMING_1 0x000C 37 #define MIC_IMG_SIZE 0x0010 38 #define MIC_INPUT_TIMING_0 0x0014 39 #define MIC_INPUT_TIMING_1 0x0018 40 #define MIC_2D_OUTPUT_TIMING_0 0x001C 41 #define MIC_2D_OUTPUT_TIMING_1 0x0020 42 #define MIC_2D_OUTPUT_TIMING_2 0x0024 43 #define MIC_3D_OUTPUT_TIMING_0 0x0028 44 #define MIC_3D_OUTPUT_TIMING_1 0x002C 45 #define MIC_3D_OUTPUT_TIMING_2 0x0030 46 #define MIC_CORE_PARA_0 0x0034 47 #define MIC_CORE_PARA_1 0x0038 48 #define MIC_CTC_CTRL 0x0040 49 #define MIC_RD_DATA 0x0044 50 51 #define MIC_UPD_REG (1 << 31) 52 #define MIC_ON_REG (1 << 30) 53 #define MIC_TD_ON_REG (1 << 29) 54 #define MIC_BS_CHG_OUT (1 << 16) 55 #define MIC_VIDEO_TYPE(x) (((x) & 0xf) << 12) 56 #define MIC_PSR_EN (1 << 5) 57 #define MIC_SW_RST (1 << 4) 58 #define MIC_ALL_RST (1 << 3) 59 #define MIC_CORE_VER_CONTROL (1 << 2) 60 #define MIC_MODE_SEL_COMMAND_MODE (1 << 1) 61 #define MIC_MODE_SEL_MASK (1 << 1) 62 #define MIC_CORE_EN (1 << 0) 63 64 #define MIC_V_PULSE_WIDTH(x) (((x) & 0x3fff) << 16) 65 #define MIC_V_PERIOD_LINE(x) ((x) & 0x3fff) 66 67 #define MIC_VBP_SIZE(x) (((x) & 0x3fff) << 16) 68 #define MIC_VFP_SIZE(x) ((x) & 0x3fff) 69 70 #define MIC_IMG_V_SIZE(x) (((x) & 0x3fff) << 16) 71 #define MIC_IMG_H_SIZE(x) ((x) & 0x3fff) 72 73 #define MIC_H_PULSE_WIDTH_IN(x) (((x) & 0x3fff) << 16) 74 #define MIC_H_PERIOD_PIXEL_IN(x) ((x) & 0x3fff) 75 76 #define MIC_HBP_SIZE_IN(x) (((x) & 0x3fff) << 16) 77 #define MIC_HFP_SIZE_IN(x) ((x) & 0x3fff) 78 79 #define MIC_H_PULSE_WIDTH_2D(x) (((x) & 0x3fff) << 16) 80 #define MIC_H_PERIOD_PIXEL_2D(x) ((x) & 0x3fff) 81 82 #define MIC_HBP_SIZE_2D(x) (((x) & 0x3fff) << 16) 83 #define MIC_HFP_SIZE_2D(x) ((x) & 0x3fff) 84 85 #define MIC_BS_SIZE_2D(x) ((x) & 0x3fff) 86 87 enum { 88 ENDPOINT_DECON_NODE, 89 ENDPOINT_DSI_NODE, 90 NUM_ENDPOINTS 91 }; 92 93 static char *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_encoder *encoder; 106 struct drm_bridge bridge; 107 108 bool enabled; 109 }; 110 111 static void mic_set_path(struct exynos_mic *mic, bool enable) 112 { 113 int ret; 114 unsigned int val; 115 116 ret = regmap_read(mic->sysreg, DSD_CFG_MUX, &val); 117 if (ret) { 118 DRM_ERROR("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_ERROR("mic: Failed to read system register\n"); 135 } 136 137 static 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 155 static 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 179 static 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 190 static 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_DEBUG("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 212 static 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 231 static struct device_node *get_remote_node(struct device_node *from, int reg) 232 { 233 struct device_node *endpoint = NULL, *remote_node = NULL; 234 235 endpoint = of_graph_get_endpoint_by_regs(from, reg, -1); 236 if (!endpoint) { 237 DRM_ERROR("mic: Failed to find remote port from %s", 238 from->full_name); 239 goto exit; 240 } 241 242 remote_node = of_graph_get_remote_port_parent(endpoint); 243 if (!remote_node) { 244 DRM_ERROR("mic: Failed to find remote port parent from %s", 245 from->full_name); 246 goto exit; 247 } 248 249 exit: 250 of_node_put(endpoint); 251 return remote_node; 252 } 253 254 static int parse_dt(struct exynos_mic *mic) 255 { 256 int ret = 0, i, j; 257 struct device_node *remote_node; 258 struct device_node *nodes[3]; 259 260 /* 261 * The order of endpoints does matter. 262 * The first node must be for decon and the second one must be for dsi. 263 */ 264 for (i = 0, j = 0; i < NUM_ENDPOINTS; i++) { 265 remote_node = get_remote_node(mic->dev->of_node, i); 266 if (!remote_node) { 267 ret = -EPIPE; 268 goto exit; 269 } 270 nodes[j++] = remote_node; 271 272 switch (i) { 273 case ENDPOINT_DECON_NODE: 274 /* decon node */ 275 if (of_get_child_by_name(remote_node, 276 "i80-if-timings")) 277 mic->i80_mode = 1; 278 279 break; 280 case ENDPOINT_DSI_NODE: 281 /* panel node */ 282 remote_node = get_remote_node(remote_node, 1); 283 if (!remote_node) { 284 ret = -EPIPE; 285 goto exit; 286 } 287 nodes[j++] = remote_node; 288 289 ret = of_get_videomode(remote_node, 290 &mic->vm, 0); 291 if (ret) { 292 DRM_ERROR("mic: failed to get videomode"); 293 goto exit; 294 } 295 296 break; 297 default: 298 DRM_ERROR("mic: Unknown endpoint from MIC"); 299 break; 300 } 301 } 302 303 exit: 304 while (--j > -1) 305 of_node_put(nodes[j]); 306 307 return ret; 308 } 309 310 static void mic_disable(struct drm_bridge *bridge) { } 311 312 static void mic_post_disable(struct drm_bridge *bridge) 313 { 314 struct exynos_mic *mic = bridge->driver_private; 315 int i; 316 317 mutex_lock(&mic_mutex); 318 if (!mic->enabled) 319 goto already_disabled; 320 321 mic_set_path(mic, 0); 322 323 for (i = NUM_CLKS - 1; i > -1; i--) 324 clk_disable_unprepare(mic->clks[i]); 325 326 mic->enabled = 0; 327 328 already_disabled: 329 mutex_unlock(&mic_mutex); 330 } 331 332 static void mic_pre_enable(struct drm_bridge *bridge) 333 { 334 struct exynos_mic *mic = bridge->driver_private; 335 int ret, i; 336 337 mutex_lock(&mic_mutex); 338 if (mic->enabled) 339 goto already_enabled; 340 341 for (i = 0; i < NUM_CLKS; i++) { 342 ret = clk_prepare_enable(mic->clks[i]); 343 if (ret < 0) { 344 DRM_ERROR("Failed to enable clock (%s)\n", 345 clk_names[i]); 346 goto turn_off_clks; 347 } 348 } 349 350 mic_set_path(mic, 1); 351 352 ret = mic_sw_reset(mic); 353 if (ret) { 354 DRM_ERROR("Failed to reset\n"); 355 goto turn_off_clks; 356 } 357 358 if (!mic->i80_mode) 359 mic_set_porch_timing(mic); 360 mic_set_img_size(mic); 361 mic_set_output_timing(mic); 362 mic_set_reg_on(mic, 1); 363 mic->enabled = 1; 364 mutex_unlock(&mic_mutex); 365 366 return; 367 368 turn_off_clks: 369 while (--i > -1) 370 clk_disable_unprepare(mic->clks[i]); 371 already_enabled: 372 mutex_unlock(&mic_mutex); 373 } 374 375 static void mic_enable(struct drm_bridge *bridge) { } 376 377 static const struct drm_bridge_funcs mic_bridge_funcs = { 378 .disable = mic_disable, 379 .post_disable = mic_post_disable, 380 .pre_enable = mic_pre_enable, 381 .enable = mic_enable, 382 }; 383 384 static int exynos_mic_bind(struct device *dev, struct device *master, 385 void *data) 386 { 387 struct exynos_mic *mic = dev_get_drvdata(dev); 388 int ret; 389 390 mic->bridge.funcs = &mic_bridge_funcs; 391 mic->bridge.of_node = dev->of_node; 392 mic->bridge.driver_private = mic; 393 ret = drm_bridge_add(&mic->bridge); 394 if (ret) 395 DRM_ERROR("mic: Failed to add MIC to the global bridge list\n"); 396 397 return ret; 398 } 399 400 static void exynos_mic_unbind(struct device *dev, struct device *master, 401 void *data) 402 { 403 struct exynos_mic *mic = dev_get_drvdata(dev); 404 int i; 405 406 mutex_lock(&mic_mutex); 407 if (!mic->enabled) 408 goto already_disabled; 409 410 for (i = NUM_CLKS - 1; i > -1; i--) 411 clk_disable_unprepare(mic->clks[i]); 412 413 already_disabled: 414 mutex_unlock(&mic_mutex); 415 416 drm_bridge_remove(&mic->bridge); 417 } 418 419 static const struct component_ops exynos_mic_component_ops = { 420 .bind = exynos_mic_bind, 421 .unbind = exynos_mic_unbind, 422 }; 423 424 static int exynos_mic_probe(struct platform_device *pdev) 425 { 426 struct device *dev = &pdev->dev; 427 struct exynos_mic *mic; 428 struct resource res; 429 int ret, i; 430 431 mic = devm_kzalloc(dev, sizeof(*mic), GFP_KERNEL); 432 if (!mic) { 433 DRM_ERROR("mic: Failed to allocate memory for MIC object\n"); 434 ret = -ENOMEM; 435 goto err; 436 } 437 438 mic->dev = dev; 439 440 ret = parse_dt(mic); 441 if (ret) 442 goto err; 443 444 ret = of_address_to_resource(dev->of_node, 0, &res); 445 if (ret) { 446 DRM_ERROR("mic: Failed to get mem region for MIC\n"); 447 goto err; 448 } 449 mic->reg = devm_ioremap(dev, res.start, resource_size(&res)); 450 if (!mic->reg) { 451 DRM_ERROR("mic: Failed to remap for MIC\n"); 452 ret = -ENOMEM; 453 goto err; 454 } 455 456 mic->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node, 457 "samsung,disp-syscon"); 458 if (IS_ERR(mic->sysreg)) { 459 DRM_ERROR("mic: Failed to get system register.\n"); 460 ret = PTR_ERR(mic->sysreg); 461 goto err; 462 } 463 464 for (i = 0; i < NUM_CLKS; i++) { 465 mic->clks[i] = devm_clk_get(dev, clk_names[i]); 466 if (IS_ERR(mic->clks[i])) { 467 DRM_ERROR("mic: Failed to get clock (%s)\n", 468 clk_names[i]); 469 ret = PTR_ERR(mic->clks[i]); 470 goto err; 471 } 472 } 473 474 platform_set_drvdata(pdev, mic); 475 476 DRM_DEBUG_KMS("MIC has been probed\n"); 477 return component_add(dev, &exynos_mic_component_ops); 478 479 err: 480 return ret; 481 } 482 483 static int exynos_mic_remove(struct platform_device *pdev) 484 { 485 component_del(&pdev->dev, &exynos_mic_component_ops); 486 return 0; 487 } 488 489 static const struct of_device_id exynos_mic_of_match[] = { 490 { .compatible = "samsung,exynos5433-mic" }, 491 { } 492 }; 493 MODULE_DEVICE_TABLE(of, exynos_mic_of_match); 494 495 struct platform_driver mic_driver = { 496 .probe = exynos_mic_probe, 497 .remove = exynos_mic_remove, 498 .driver = { 499 .name = "exynos-mic", 500 .owner = THIS_MODULE, 501 .of_match_table = exynos_mic_of_match, 502 }, 503 }; 504