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

Merge tag 'topic/crc-pmic-2015-07-23' of git://anongit.freedesktop.org/drm-intel into drm-next

crystalcove pmic support from Shobhit. Patch series has all acks/r-bs from
other mainainers so ok to pull into drm-next. But I'm cc'ing all other
maintainers as fyi and in case they want to pull it into their trees too
to avoid conflicts.

* tag 'topic/crc-pmic-2015-07-23' of git://anongit.freedesktop.org/drm-intel:
mfd: Add GPIOLIB dependency if INTEL_SOC_PMIC is to be enabled
drm/i915: Backlight control using CRC PMIC based PWM driver
drm/i915: Use the CRC gpio for panel enable/disable
pwm: crc: Add Crystalcove (CRC) PWM driver
mfd: intel_soc_pmic_core: ADD PWM lookup table for CRC PMIC based PWM
mfd: intel_soc_pmic_crc: Add PWM cell device for Crystalcove PMIC
mfd: intel_soc_pmic_core: Add lookup table for Panel Control as GPIO signal
gpiolib: Add support for removing registered consumer lookup table

+336 -7
+13
drivers/gpio/gpiolib.c
··· 1672 1672 mutex_unlock(&gpio_lookup_lock); 1673 1673 } 1674 1674 1675 + /** 1676 + * gpiod_remove_lookup_table() - unregister GPIO device consumers 1677 + * @table: table of consumers to unregister 1678 + */ 1679 + void gpiod_remove_lookup_table(struct gpiod_lookup_table *table) 1680 + { 1681 + mutex_lock(&gpio_lookup_lock); 1682 + 1683 + list_del(&table->list); 1684 + 1685 + mutex_unlock(&gpio_lookup_lock); 1686 + } 1687 + 1675 1688 static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, 1676 1689 unsigned int idx, 1677 1690 enum gpio_lookup_flags *flags)
+7
drivers/gpu/drm/i915/intel_bios.h
··· 778 778 #define MIPI_DSI_UNDEFINED_PANEL_ID 0 779 779 #define MIPI_DSI_GENERIC_PANEL_ID 1 780 780 781 + /* 782 + * PMIC vs SoC Backlight support specified in pwm_blc 783 + * field in mipi_config block below. 784 + */ 785 + #define PPS_BLC_PMIC 0 786 + #define PPS_BLC_SOC 1 787 + 781 788 struct mipi_config { 782 789 u16 panel_id; 783 790
+4
drivers/gpu/drm/i915/intel_drv.h
··· 177 177 bool enabled; 178 178 bool combination_mode; /* gen 2/4 only */ 179 179 bool active_low_pwm; 180 + 181 + /* PWM chip */ 182 + struct pwm_device *pwm; 183 + 180 184 struct backlight_device *device; 181 185 } backlight; 182 186
+35 -2
drivers/gpu/drm/i915/intel_dsi.c
··· 31 31 #include <drm/drm_panel.h> 32 32 #include <drm/drm_mipi_dsi.h> 33 33 #include <linux/slab.h> 34 + #include <linux/gpio/consumer.h> 34 35 #include "i915_drv.h" 35 36 #include "intel_drv.h" 36 37 #include "intel_dsi.h" ··· 397 396 398 397 intel_dsi_port_enable(encoder); 399 398 } 399 + 400 + intel_panel_enable_backlight(intel_dsi->attached_connector); 400 401 } 401 402 402 403 static void intel_dsi_pre_enable(struct intel_encoder *encoder) ··· 412 409 u32 tmp; 413 410 414 411 DRM_DEBUG_KMS("\n"); 412 + 413 + /* Panel Enable over CRC PMIC */ 414 + if (intel_dsi->gpio_panel) 415 + gpiod_set_value_cansleep(intel_dsi->gpio_panel, 1); 416 + 417 + msleep(intel_dsi->panel_on_delay); 415 418 416 419 /* Disable DPOunit clock gating, can stall pipe 417 420 * and we need DPLL REFA always enabled */ ··· 435 426 436 427 /* put device in ready state */ 437 428 intel_dsi_device_ready(encoder); 438 - 439 - msleep(intel_dsi->panel_on_delay); 440 429 441 430 drm_panel_prepare(intel_dsi->panel); 442 431 ··· 462 455 enum port port; 463 456 464 457 DRM_DEBUG_KMS("\n"); 458 + 459 + intel_panel_disable_backlight(intel_dsi->attached_connector); 465 460 466 461 if (is_vid_mode(intel_dsi)) { 467 462 /* Send Shutdown command to the panel in LP mode */ ··· 580 571 581 572 msleep(intel_dsi->panel_off_delay); 582 573 msleep(intel_dsi->panel_pwr_cycle_delay); 574 + 575 + /* Panel Disable over CRC PMIC */ 576 + if (intel_dsi->gpio_panel) 577 + gpiod_set_value_cansleep(intel_dsi->gpio_panel, 0); 583 578 } 584 579 585 580 static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, ··· 963 950 /* XXX: Logically this call belongs in the panel driver. */ 964 951 drm_panel_remove(intel_dsi->panel); 965 952 } 953 + 954 + /* dispose of the gpios */ 955 + if (intel_dsi->gpio_panel) 956 + gpiod_put(intel_dsi->gpio_panel); 957 + 966 958 intel_encoder_destroy(encoder); 967 959 } 968 960 ··· 1083 1065 goto err; 1084 1066 } 1085 1067 1068 + /* 1069 + * In case of BYT with CRC PMIC, we need to use GPIO for 1070 + * Panel control. 1071 + */ 1072 + if (dev_priv->vbt.dsi.config->pwm_blc == PPS_BLC_PMIC) { 1073 + intel_dsi->gpio_panel = 1074 + gpiod_get(dev->dev, "panel", GPIOD_OUT_HIGH); 1075 + 1076 + if (IS_ERR(intel_dsi->gpio_panel)) { 1077 + DRM_ERROR("Failed to own gpio for panel control\n"); 1078 + intel_dsi->gpio_panel = NULL; 1079 + } 1080 + } 1081 + 1086 1082 intel_encoder->type = INTEL_OUTPUT_DSI; 1087 1083 intel_encoder->cloneable = 0; 1088 1084 drm_connector_init(dev, connector, &intel_dsi_connector_funcs, ··· 1130 1098 } 1131 1099 1132 1100 intel_panel_init(&intel_connector->panel, fixed_mode, NULL); 1101 + intel_panel_setup_backlight(connector, INVALID_PIPE); 1133 1102 1134 1103 return; 1135 1104
+3
drivers/gpu/drm/i915/intel_dsi.h
··· 42 42 struct drm_panel *panel; 43 43 struct intel_dsi_host *dsi_hosts[I915_MAX_PORTS]; 44 44 45 + /* GPIO Desc for CRC based Panel control */ 46 + struct gpio_desc *gpio_panel; 47 + 45 48 struct intel_connector *attached_connector; 46 49 47 50 /* bit mask of ports being driven */
+89 -5
drivers/gpu/drm/i915/intel_panel.c
··· 32 32 33 33 #include <linux/kernel.h> 34 34 #include <linux/moduleparam.h> 35 + #include <linux/pwm.h> 35 36 #include "intel_drv.h" 37 + 38 + #define CRC_PMIC_PWM_PERIOD_NS 21333 36 39 37 40 void 38 41 intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode, ··· 547 544 return I915_READ(BXT_BLC_PWM_DUTY1); 548 545 } 549 546 547 + static u32 pwm_get_backlight(struct intel_connector *connector) 548 + { 549 + struct intel_panel *panel = &connector->panel; 550 + int duty_ns; 551 + 552 + duty_ns = pwm_get_duty_cycle(panel->backlight.pwm); 553 + return DIV_ROUND_UP(duty_ns * 100, CRC_PMIC_PWM_PERIOD_NS); 554 + } 555 + 550 556 static u32 intel_panel_get_backlight(struct intel_connector *connector) 551 557 { 552 558 struct drm_device *dev = connector->base.dev; ··· 642 630 struct drm_i915_private *dev_priv = dev->dev_private; 643 631 644 632 I915_WRITE(BXT_BLC_PWM_DUTY1, level); 633 + } 634 + 635 + static void pwm_set_backlight(struct intel_connector *connector, u32 level) 636 + { 637 + struct intel_panel *panel = &connector->panel; 638 + int duty_ns = DIV_ROUND_UP(level * CRC_PMIC_PWM_PERIOD_NS, 100); 639 + 640 + pwm_config(panel->backlight.pwm, duty_ns, CRC_PMIC_PWM_PERIOD_NS); 645 641 } 646 642 647 643 static void ··· 787 767 788 768 tmp = I915_READ(BXT_BLC_PWM_CTL1); 789 769 I915_WRITE(BXT_BLC_PWM_CTL1, tmp & ~BXT_BLC_PWM_ENABLE); 770 + } 771 + 772 + static void pwm_disable_backlight(struct intel_connector *connector) 773 + { 774 + struct intel_panel *panel = &connector->panel; 775 + 776 + /* Disable the backlight */ 777 + pwm_config(panel->backlight.pwm, 0, CRC_PMIC_PWM_PERIOD_NS); 778 + usleep_range(2000, 3000); 779 + pwm_disable(panel->backlight.pwm); 790 780 } 791 781 792 782 void intel_panel_disable_backlight(struct intel_connector *connector) ··· 1038 1008 I915_WRITE(BXT_BLC_PWM_CTL1, pwm_ctl); 1039 1009 POSTING_READ(BXT_BLC_PWM_CTL1); 1040 1010 I915_WRITE(BXT_BLC_PWM_CTL1, pwm_ctl | BXT_BLC_PWM_ENABLE); 1011 + } 1012 + 1013 + static void pwm_enable_backlight(struct intel_connector *connector) 1014 + { 1015 + struct intel_panel *panel = &connector->panel; 1016 + 1017 + pwm_enable(panel->backlight.pwm); 1018 + intel_panel_actually_set_backlight(connector, panel->backlight.level); 1041 1019 } 1042 1020 1043 1021 void intel_panel_enable_backlight(struct intel_connector *connector) ··· 1424 1386 return 0; 1425 1387 } 1426 1388 1389 + static int pwm_setup_backlight(struct intel_connector *connector, 1390 + enum pipe pipe) 1391 + { 1392 + struct drm_device *dev = connector->base.dev; 1393 + struct intel_panel *panel = &connector->panel; 1394 + int retval; 1395 + 1396 + /* Get the PWM chip for backlight control */ 1397 + panel->backlight.pwm = pwm_get(dev->dev, "pwm_backlight"); 1398 + if (IS_ERR(panel->backlight.pwm)) { 1399 + DRM_ERROR("Failed to own the pwm chip\n"); 1400 + panel->backlight.pwm = NULL; 1401 + return -ENODEV; 1402 + } 1403 + 1404 + retval = pwm_config(panel->backlight.pwm, CRC_PMIC_PWM_PERIOD_NS, 1405 + CRC_PMIC_PWM_PERIOD_NS); 1406 + if (retval < 0) { 1407 + DRM_ERROR("Failed to configure the pwm chip\n"); 1408 + pwm_put(panel->backlight.pwm); 1409 + panel->backlight.pwm = NULL; 1410 + return retval; 1411 + } 1412 + 1413 + panel->backlight.min = 0; /* 0% */ 1414 + panel->backlight.max = 100; /* 100% */ 1415 + panel->backlight.level = DIV_ROUND_UP( 1416 + pwm_get_duty_cycle(panel->backlight.pwm) * 100, 1417 + CRC_PMIC_PWM_PERIOD_NS); 1418 + panel->backlight.enabled = panel->backlight.level != 0; 1419 + 1420 + return 0; 1421 + } 1422 + 1427 1423 int intel_panel_setup_backlight(struct drm_connector *connector, enum pipe pipe) 1428 1424 { 1429 1425 struct drm_device *dev = connector->dev; ··· 1501 1429 struct intel_connector *intel_connector = to_intel_connector(connector); 1502 1430 struct intel_panel *panel = &intel_connector->panel; 1503 1431 1432 + /* dispose of the pwm */ 1433 + if (panel->backlight.pwm) 1434 + pwm_put(panel->backlight.pwm); 1435 + 1504 1436 panel->backlight.present = false; 1505 1437 } 1506 1438 ··· 1532 1456 dev_priv->display.set_backlight = pch_set_backlight; 1533 1457 dev_priv->display.get_backlight = pch_get_backlight; 1534 1458 } else if (IS_VALLEYVIEW(dev)) { 1535 - dev_priv->display.setup_backlight = vlv_setup_backlight; 1536 - dev_priv->display.enable_backlight = vlv_enable_backlight; 1537 - dev_priv->display.disable_backlight = vlv_disable_backlight; 1538 - dev_priv->display.set_backlight = vlv_set_backlight; 1539 - dev_priv->display.get_backlight = vlv_get_backlight; 1459 + if (dev_priv->vbt.has_mipi) { 1460 + dev_priv->display.setup_backlight = pwm_setup_backlight; 1461 + dev_priv->display.enable_backlight = pwm_enable_backlight; 1462 + dev_priv->display.disable_backlight = pwm_disable_backlight; 1463 + dev_priv->display.set_backlight = pwm_set_backlight; 1464 + dev_priv->display.get_backlight = pwm_get_backlight; 1465 + } else { 1466 + dev_priv->display.setup_backlight = vlv_setup_backlight; 1467 + dev_priv->display.enable_backlight = vlv_enable_backlight; 1468 + dev_priv->display.disable_backlight = vlv_disable_backlight; 1469 + dev_priv->display.set_backlight = vlv_set_backlight; 1470 + dev_priv->display.get_backlight = vlv_get_backlight; 1471 + } 1540 1472 } else if (IS_GEN4(dev)) { 1541 1473 dev_priv->display.setup_backlight = i965_setup_backlight; 1542 1474 dev_priv->display.enable_backlight = i965_enable_backlight;
+1
drivers/mfd/Kconfig
··· 318 318 319 319 config INTEL_SOC_PMIC 320 320 bool "Support for Intel Atom SoC PMIC" 321 + depends on GPIOLIB 321 322 depends on I2C=y 322 323 select MFD_CORE 323 324 select REGMAP_I2C
+29
drivers/mfd/intel_soc_pmic_core.c
··· 24 24 #include <linux/acpi.h> 25 25 #include <linux/regmap.h> 26 26 #include <linux/mfd/intel_soc_pmic.h> 27 + #include <linux/gpio/machine.h> 28 + #include <linux/pwm.h> 27 29 #include "intel_soc_pmic_core.h" 30 + 31 + /* Lookup table for the Panel Enable/Disable line as GPIO signals */ 32 + static struct gpiod_lookup_table panel_gpio_table = { 33 + /* Intel GFX is consumer */ 34 + .dev_id = "0000:00:02.0", 35 + .table = { 36 + /* Panel EN/DISABLE */ 37 + GPIO_LOOKUP("gpio_crystalcove", 94, "panel", GPIO_ACTIVE_HIGH), 38 + }, 39 + }; 40 + 41 + /* PWM consumed by the Intel GFX */ 42 + static struct pwm_lookup crc_pwm_lookup[] = { 43 + PWM_LOOKUP("crystal_cove_pwm", 0, "0000:00:02.0", "pwm_backlight", 0, PWM_POLARITY_NORMAL), 44 + }; 28 45 29 46 static int intel_soc_pmic_find_gpio_irq(struct device *dev) 30 47 { ··· 102 85 if (ret) 103 86 dev_warn(dev, "Can't enable IRQ as wake source: %d\n", ret); 104 87 88 + /* Add lookup table binding for Panel Control to the GPIO Chip */ 89 + gpiod_add_lookup_table(&panel_gpio_table); 90 + 91 + /* Add lookup table for crc-pwm */ 92 + pwm_add_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup)); 93 + 105 94 ret = mfd_add_devices(dev, -1, config->cell_dev, 106 95 config->n_cell_devs, NULL, 0, 107 96 regmap_irq_get_domain(pmic->irq_chip_data)); ··· 126 103 struct intel_soc_pmic *pmic = dev_get_drvdata(&i2c->dev); 127 104 128 105 regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data); 106 + 107 + /* Remove lookup table for Panel Control from the GPIO Chip */ 108 + gpiod_remove_lookup_table(&panel_gpio_table); 109 + 110 + /* remove crc-pwm lookup table */ 111 + pwm_remove_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup)); 129 112 130 113 mfd_remove_devices(&i2c->dev); 131 114
+3
drivers/mfd/intel_soc_pmic_crc.c
··· 109 109 { 110 110 .name = "crystal_cove_pmic", 111 111 }, 112 + { 113 + .name = "crystal_cove_pwm", 114 + }, 112 115 }; 113 116 114 117 static const struct regmap_config crystal_cove_regmap_config = {
+7
drivers/pwm/Kconfig
··· 111 111 To compile this driver as a module, choose M here: the module 112 112 will be called pwm-clps711x. 113 113 114 + config PWM_CRC 115 + bool "Intel Crystalcove (CRC) PWM support" 116 + depends on X86 && INTEL_SOC_PMIC 117 + help 118 + Generic PWM framework driver for Crystalcove (CRC) PMIC based PWM 119 + control. 120 + 114 121 config PWM_EP93XX 115 122 tristate "Cirrus Logic EP93xx PWM support" 116 123 depends on ARCH_EP93XX
+1
drivers/pwm/Makefile
··· 8 8 obj-$(CONFIG_PWM_BCM2835) += pwm-bcm2835.o 9 9 obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o 10 10 obj-$(CONFIG_PWM_CLPS711X) += pwm-clps711x.o 11 + obj-$(CONFIG_PWM_CRC) += pwm-crc.o 11 12 obj-$(CONFIG_PWM_EP93XX) += pwm-ep93xx.o 12 13 obj-$(CONFIG_PWM_FSL_FTM) += pwm-fsl-ftm.o 13 14 obj-$(CONFIG_PWM_IMG) += pwm-img.o
+143
drivers/pwm/pwm-crc.c
··· 1 + /* 2 + * Copyright (C) 2015 Intel Corporation. All rights reserved. 3 + * 4 + * This program is free software; you can redistribute it and/or 5 + * modify it under the terms of the GNU General Public License version 6 + * 2 as published by the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope that it will be useful, 9 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 + * GNU General Public License for more details. 12 + * 13 + * Author: Shobhit Kumar <shobhit.kumar@intel.com> 14 + */ 15 + 16 + #include <linux/platform_device.h> 17 + #include <linux/regmap.h> 18 + #include <linux/mfd/intel_soc_pmic.h> 19 + #include <linux/pwm.h> 20 + 21 + #define PWM0_CLK_DIV 0x4B 22 + #define PWM_OUTPUT_ENABLE BIT(7) 23 + #define PWM_DIV_CLK_0 0x00 /* DIVIDECLK = BASECLK */ 24 + #define PWM_DIV_CLK_100 0x63 /* DIVIDECLK = BASECLK/100 */ 25 + #define PWM_DIV_CLK_128 0x7F /* DIVIDECLK = BASECLK/128 */ 26 + 27 + #define PWM0_DUTY_CYCLE 0x4E 28 + #define BACKLIGHT_EN 0x51 29 + 30 + #define PWM_MAX_LEVEL 0xFF 31 + 32 + #define PWM_BASE_CLK 6000000 /* 6 MHz */ 33 + #define PWM_MAX_PERIOD_NS 21333 /* 46.875KHz */ 34 + 35 + /** 36 + * struct crystalcove_pwm - Crystal Cove PWM controller 37 + * @chip: the abstract pwm_chip structure. 38 + * @regmap: the regmap from the parent device. 39 + */ 40 + struct crystalcove_pwm { 41 + struct pwm_chip chip; 42 + struct regmap *regmap; 43 + }; 44 + 45 + static inline struct crystalcove_pwm *to_crc_pwm(struct pwm_chip *pc) 46 + { 47 + return container_of(pc, struct crystalcove_pwm, chip); 48 + } 49 + 50 + static int crc_pwm_enable(struct pwm_chip *c, struct pwm_device *pwm) 51 + { 52 + struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); 53 + 54 + regmap_write(crc_pwm->regmap, BACKLIGHT_EN, 1); 55 + 56 + return 0; 57 + } 58 + 59 + static void crc_pwm_disable(struct pwm_chip *c, struct pwm_device *pwm) 60 + { 61 + struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); 62 + 63 + regmap_write(crc_pwm->regmap, BACKLIGHT_EN, 0); 64 + } 65 + 66 + static int crc_pwm_config(struct pwm_chip *c, struct pwm_device *pwm, 67 + int duty_ns, int period_ns) 68 + { 69 + struct crystalcove_pwm *crc_pwm = to_crc_pwm(c); 70 + struct device *dev = crc_pwm->chip.dev; 71 + int level; 72 + 73 + if (period_ns > PWM_MAX_PERIOD_NS) { 74 + dev_err(dev, "un-supported period_ns\n"); 75 + return -EINVAL; 76 + } 77 + 78 + if (pwm->period != period_ns) { 79 + int clk_div; 80 + 81 + /* changing the clk divisor, need to disable fisrt */ 82 + crc_pwm_disable(c, pwm); 83 + clk_div = PWM_BASE_CLK * period_ns / NSEC_PER_SEC; 84 + 85 + regmap_write(crc_pwm->regmap, PWM0_CLK_DIV, 86 + clk_div | PWM_OUTPUT_ENABLE); 87 + 88 + /* enable back */ 89 + crc_pwm_enable(c, pwm); 90 + } 91 + 92 + /* change the pwm duty cycle */ 93 + level = duty_ns * PWM_MAX_LEVEL / period_ns; 94 + regmap_write(crc_pwm->regmap, PWM0_DUTY_CYCLE, level); 95 + 96 + return 0; 97 + } 98 + 99 + static const struct pwm_ops crc_pwm_ops = { 100 + .config = crc_pwm_config, 101 + .enable = crc_pwm_enable, 102 + .disable = crc_pwm_disable, 103 + }; 104 + 105 + static int crystalcove_pwm_probe(struct platform_device *pdev) 106 + { 107 + struct crystalcove_pwm *pwm; 108 + struct device *dev = pdev->dev.parent; 109 + struct intel_soc_pmic *pmic = dev_get_drvdata(dev); 110 + 111 + pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); 112 + if (!pwm) 113 + return -ENOMEM; 114 + 115 + pwm->chip.dev = &pdev->dev; 116 + pwm->chip.ops = &crc_pwm_ops; 117 + pwm->chip.base = -1; 118 + pwm->chip.npwm = 1; 119 + 120 + /* get the PMIC regmap */ 121 + pwm->regmap = pmic->regmap; 122 + 123 + platform_set_drvdata(pdev, pwm); 124 + 125 + return pwmchip_add(&pwm->chip); 126 + } 127 + 128 + static int crystalcove_pwm_remove(struct platform_device *pdev) 129 + { 130 + struct crystalcove_pwm *pwm = platform_get_drvdata(pdev); 131 + 132 + return pwmchip_remove(&pwm->chip); 133 + } 134 + 135 + static struct platform_driver crystalcove_pwm_driver = { 136 + .probe = crystalcove_pwm_probe, 137 + .remove = crystalcove_pwm_remove, 138 + .driver = { 139 + .name = "crystal_cove_pwm", 140 + }, 141 + }; 142 + 143 + builtin_platform_driver(crystalcove_pwm_driver);
+1
include/linux/gpio/machine.h
··· 57 57 } 58 58 59 59 void gpiod_add_lookup_table(struct gpiod_lookup_table *table); 60 + void gpiod_remove_lookup_table(struct gpiod_lookup_table *table); 60 61 61 62 #endif /* __LINUX_GPIO_MACHINE_H */