Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.18-rc2 468 lines 11 kB view raw
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 <linux/pm_runtime.h> 23#include <drm/drmP.h> 24#include <drm/drm_encoder.h> 25#include <linux/mfd/syscon.h> 26#include <linux/regmap.h> 27 28#include "exynos_drm_drv.h" 29 30/* Sysreg registers for MIC */ 31#define DSD_CFG_MUX 0x1004 32#define MIC0_RGB_MUX (1 << 0) 33#define MIC0_I80_MUX (1 << 1) 34#define MIC0_ON_MUX (1 << 5) 35 36/* MIC registers */ 37#define MIC_OP 0x0 38#define MIC_IP_VER 0x0004 39#define MIC_V_TIMING_0 0x0008 40#define MIC_V_TIMING_1 0x000C 41#define MIC_IMG_SIZE 0x0010 42#define MIC_INPUT_TIMING_0 0x0014 43#define MIC_INPUT_TIMING_1 0x0018 44#define MIC_2D_OUTPUT_TIMING_0 0x001C 45#define MIC_2D_OUTPUT_TIMING_1 0x0020 46#define MIC_2D_OUTPUT_TIMING_2 0x0024 47#define MIC_3D_OUTPUT_TIMING_0 0x0028 48#define MIC_3D_OUTPUT_TIMING_1 0x002C 49#define MIC_3D_OUTPUT_TIMING_2 0x0030 50#define MIC_CORE_PARA_0 0x0034 51#define MIC_CORE_PARA_1 0x0038 52#define MIC_CTC_CTRL 0x0040 53#define MIC_RD_DATA 0x0044 54 55#define MIC_UPD_REG (1 << 31) 56#define MIC_ON_REG (1 << 30) 57#define MIC_TD_ON_REG (1 << 29) 58#define MIC_BS_CHG_OUT (1 << 16) 59#define MIC_VIDEO_TYPE(x) (((x) & 0xf) << 12) 60#define MIC_PSR_EN (1 << 5) 61#define MIC_SW_RST (1 << 4) 62#define MIC_ALL_RST (1 << 3) 63#define MIC_CORE_VER_CONTROL (1 << 2) 64#define MIC_MODE_SEL_COMMAND_MODE (1 << 1) 65#define MIC_MODE_SEL_MASK (1 << 1) 66#define MIC_CORE_EN (1 << 0) 67 68#define MIC_V_PULSE_WIDTH(x) (((x) & 0x3fff) << 16) 69#define MIC_V_PERIOD_LINE(x) ((x) & 0x3fff) 70 71#define MIC_VBP_SIZE(x) (((x) & 0x3fff) << 16) 72#define MIC_VFP_SIZE(x) ((x) & 0x3fff) 73 74#define MIC_IMG_V_SIZE(x) (((x) & 0x3fff) << 16) 75#define MIC_IMG_H_SIZE(x) ((x) & 0x3fff) 76 77#define MIC_H_PULSE_WIDTH_IN(x) (((x) & 0x3fff) << 16) 78#define MIC_H_PERIOD_PIXEL_IN(x) ((x) & 0x3fff) 79 80#define MIC_HBP_SIZE_IN(x) (((x) & 0x3fff) << 16) 81#define MIC_HFP_SIZE_IN(x) ((x) & 0x3fff) 82 83#define MIC_H_PULSE_WIDTH_2D(x) (((x) & 0x3fff) << 16) 84#define MIC_H_PERIOD_PIXEL_2D(x) ((x) & 0x3fff) 85 86#define MIC_HBP_SIZE_2D(x) (((x) & 0x3fff) << 16) 87#define MIC_HFP_SIZE_2D(x) ((x) & 0x3fff) 88 89#define MIC_BS_SIZE_2D(x) ((x) & 0x3fff) 90 91static char *clk_names[] = { "pclk_mic0", "sclk_rgb_vclk_to_mic0" }; 92#define NUM_CLKS ARRAY_SIZE(clk_names) 93static DEFINE_MUTEX(mic_mutex); 94 95struct exynos_mic { 96 struct device *dev; 97 void __iomem *reg; 98 struct regmap *sysreg; 99 struct clk *clks[NUM_CLKS]; 100 101 bool i80_mode; 102 struct videomode vm; 103 struct drm_encoder *encoder; 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_ERROR("mic: Failed to read system register\n"); 117 return; 118 } 119 120 if (enable) { 121 if (mic->i80_mode) 122 val |= MIC0_I80_MUX; 123 else 124 val |= MIC0_RGB_MUX; 125 126 val |= MIC0_ON_MUX; 127 } else 128 val &= ~(MIC0_RGB_MUX | MIC0_I80_MUX | MIC0_ON_MUX); 129 130 ret = regmap_write(mic->sysreg, DSD_CFG_MUX, val); 131 if (ret) 132 DRM_ERROR("mic: Failed to read system register\n"); 133} 134 135static int mic_sw_reset(struct exynos_mic *mic) 136{ 137 unsigned int retry = 100; 138 int ret; 139 140 writel(MIC_SW_RST, mic->reg + MIC_OP); 141 142 while (retry-- > 0) { 143 ret = readl(mic->reg + MIC_OP); 144 if (!(ret & MIC_SW_RST)) 145 return 0; 146 147 udelay(10); 148 } 149 150 return -ETIMEDOUT; 151} 152 153static void mic_set_porch_timing(struct exynos_mic *mic) 154{ 155 struct videomode vm = mic->vm; 156 u32 reg; 157 158 reg = MIC_V_PULSE_WIDTH(vm.vsync_len) + 159 MIC_V_PERIOD_LINE(vm.vsync_len + vm.vactive + 160 vm.vback_porch + vm.vfront_porch); 161 writel(reg, mic->reg + MIC_V_TIMING_0); 162 163 reg = MIC_VBP_SIZE(vm.vback_porch) + 164 MIC_VFP_SIZE(vm.vfront_porch); 165 writel(reg, mic->reg + MIC_V_TIMING_1); 166 167 reg = MIC_V_PULSE_WIDTH(vm.hsync_len) + 168 MIC_V_PERIOD_LINE(vm.hsync_len + vm.hactive + 169 vm.hback_porch + vm.hfront_porch); 170 writel(reg, mic->reg + MIC_INPUT_TIMING_0); 171 172 reg = MIC_VBP_SIZE(vm.hback_porch) + 173 MIC_VFP_SIZE(vm.hfront_porch); 174 writel(reg, mic->reg + MIC_INPUT_TIMING_1); 175} 176 177static void mic_set_img_size(struct exynos_mic *mic) 178{ 179 struct videomode *vm = &mic->vm; 180 u32 reg; 181 182 reg = MIC_IMG_H_SIZE(vm->hactive) + 183 MIC_IMG_V_SIZE(vm->vactive); 184 185 writel(reg, mic->reg + MIC_IMG_SIZE); 186} 187 188static void mic_set_output_timing(struct exynos_mic *mic) 189{ 190 struct videomode vm = mic->vm; 191 u32 reg, bs_size_2d; 192 193 DRM_DEBUG("w: %u, h: %u\n", vm.hactive, vm.vactive); 194 bs_size_2d = ((vm.hactive >> 2) << 1) + (vm.vactive % 4); 195 reg = MIC_BS_SIZE_2D(bs_size_2d); 196 writel(reg, mic->reg + MIC_2D_OUTPUT_TIMING_2); 197 198 if (!mic->i80_mode) { 199 reg = MIC_H_PULSE_WIDTH_2D(vm.hsync_len) + 200 MIC_H_PERIOD_PIXEL_2D(vm.hsync_len + bs_size_2d + 201 vm.hback_porch + vm.hfront_porch); 202 writel(reg, mic->reg + MIC_2D_OUTPUT_TIMING_0); 203 204 reg = MIC_HBP_SIZE_2D(vm.hback_porch) + 205 MIC_H_PERIOD_PIXEL_2D(vm.hfront_porch); 206 writel(reg, mic->reg + MIC_2D_OUTPUT_TIMING_1); 207 } 208} 209 210static void mic_set_reg_on(struct exynos_mic *mic, bool enable) 211{ 212 u32 reg = readl(mic->reg + MIC_OP); 213 214 if (enable) { 215 reg &= ~(MIC_MODE_SEL_MASK | MIC_CORE_VER_CONTROL | MIC_PSR_EN); 216 reg |= (MIC_CORE_EN | MIC_BS_CHG_OUT | MIC_ON_REG); 217 218 reg &= ~MIC_MODE_SEL_COMMAND_MODE; 219 if (mic->i80_mode) 220 reg |= MIC_MODE_SEL_COMMAND_MODE; 221 } else { 222 reg &= ~MIC_CORE_EN; 223 } 224 225 reg |= MIC_UPD_REG; 226 writel(reg, mic->reg + MIC_OP); 227} 228 229static void mic_disable(struct drm_bridge *bridge) { } 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 struct drm_display_mode *mode, 250 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_get_sync(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_ERROR("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 void mic_enable(struct drm_bridge *bridge) { } 298 299static const struct drm_bridge_funcs mic_bridge_funcs = { 300 .disable = mic_disable, 301 .post_disable = mic_post_disable, 302 .mode_set = mic_mode_set, 303 .pre_enable = mic_pre_enable, 304 .enable = mic_enable, 305}; 306 307static int exynos_mic_bind(struct device *dev, struct device *master, 308 void *data) 309{ 310 struct exynos_mic *mic = dev_get_drvdata(dev); 311 312 mic->bridge.driver_private = mic; 313 314 return 0; 315} 316 317static void exynos_mic_unbind(struct device *dev, struct device *master, 318 void *data) 319{ 320 struct exynos_mic *mic = dev_get_drvdata(dev); 321 322 mutex_lock(&mic_mutex); 323 if (!mic->enabled) 324 goto already_disabled; 325 326 pm_runtime_put(mic->dev); 327 328already_disabled: 329 mutex_unlock(&mic_mutex); 330} 331 332static const struct component_ops exynos_mic_component_ops = { 333 .bind = exynos_mic_bind, 334 .unbind = exynos_mic_unbind, 335}; 336 337#ifdef CONFIG_PM 338static int exynos_mic_suspend(struct device *dev) 339{ 340 struct exynos_mic *mic = dev_get_drvdata(dev); 341 int i; 342 343 for (i = NUM_CLKS - 1; i > -1; i--) 344 clk_disable_unprepare(mic->clks[i]); 345 346 return 0; 347} 348 349static int exynos_mic_resume(struct device *dev) 350{ 351 struct exynos_mic *mic = dev_get_drvdata(dev); 352 int ret, i; 353 354 for (i = 0; i < NUM_CLKS; i++) { 355 ret = clk_prepare_enable(mic->clks[i]); 356 if (ret < 0) { 357 DRM_ERROR("Failed to enable clock (%s)\n", 358 clk_names[i]); 359 while (--i > -1) 360 clk_disable_unprepare(mic->clks[i]); 361 return ret; 362 } 363 } 364 return 0; 365} 366#endif 367 368static const struct dev_pm_ops exynos_mic_pm_ops = { 369 SET_RUNTIME_PM_OPS(exynos_mic_suspend, exynos_mic_resume, NULL) 370}; 371 372static int exynos_mic_probe(struct platform_device *pdev) 373{ 374 struct device *dev = &pdev->dev; 375 struct exynos_mic *mic; 376 struct resource res; 377 int ret, i; 378 379 mic = devm_kzalloc(dev, sizeof(*mic), GFP_KERNEL); 380 if (!mic) { 381 DRM_ERROR("mic: Failed to allocate memory for MIC object\n"); 382 ret = -ENOMEM; 383 goto err; 384 } 385 386 mic->dev = dev; 387 388 ret = of_address_to_resource(dev->of_node, 0, &res); 389 if (ret) { 390 DRM_ERROR("mic: Failed to get mem region for MIC\n"); 391 goto err; 392 } 393 mic->reg = devm_ioremap(dev, res.start, resource_size(&res)); 394 if (!mic->reg) { 395 DRM_ERROR("mic: Failed to remap for MIC\n"); 396 ret = -ENOMEM; 397 goto err; 398 } 399 400 mic->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node, 401 "samsung,disp-syscon"); 402 if (IS_ERR(mic->sysreg)) { 403 DRM_ERROR("mic: Failed to get system register.\n"); 404 ret = PTR_ERR(mic->sysreg); 405 goto err; 406 } 407 408 for (i = 0; i < NUM_CLKS; i++) { 409 mic->clks[i] = devm_clk_get(dev, clk_names[i]); 410 if (IS_ERR(mic->clks[i])) { 411 DRM_ERROR("mic: Failed to get clock (%s)\n", 412 clk_names[i]); 413 ret = PTR_ERR(mic->clks[i]); 414 goto err; 415 } 416 } 417 418 platform_set_drvdata(pdev, mic); 419 420 mic->bridge.funcs = &mic_bridge_funcs; 421 mic->bridge.of_node = dev->of_node; 422 423 drm_bridge_add(&mic->bridge); 424 425 pm_runtime_enable(dev); 426 427 ret = component_add(dev, &exynos_mic_component_ops); 428 if (ret) 429 goto err_pm; 430 431 DRM_DEBUG_KMS("MIC has been probed\n"); 432 433 return 0; 434 435err_pm: 436 pm_runtime_disable(dev); 437err: 438 return ret; 439} 440 441static int exynos_mic_remove(struct platform_device *pdev) 442{ 443 struct exynos_mic *mic = platform_get_drvdata(pdev); 444 445 component_del(&pdev->dev, &exynos_mic_component_ops); 446 pm_runtime_disable(&pdev->dev); 447 448 drm_bridge_remove(&mic->bridge); 449 450 return 0; 451} 452 453static const struct of_device_id exynos_mic_of_match[] = { 454 { .compatible = "samsung,exynos5433-mic" }, 455 { } 456}; 457MODULE_DEVICE_TABLE(of, exynos_mic_of_match); 458 459struct platform_driver mic_driver = { 460 .probe = exynos_mic_probe, 461 .remove = exynos_mic_remove, 462 .driver = { 463 .name = "exynos-mic", 464 .pm = &exynos_mic_pm_ops, 465 .owner = THIS_MODULE, 466 .of_match_table = exynos_mic_of_match, 467 }, 468};