aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/gma500/cdv_device.c
diff options
context:
space:
mode:
authorAlan Cox <alan@linux.intel.com>2012-05-03 10:06:05 -0400
committerDave Airlie <airlied@redhat.com>2012-05-03 11:28:04 -0400
commit9aba9d3a2ca42572c9c196e8be6cab59b7c078b6 (patch)
tree031eadf3606808d8018b8ba3f8ab1bec49c85c40 /drivers/gpu/drm/gma500/cdv_device.c
parentbb84977941ad85a5c0b9ff4fd5331913e31107c4 (diff)
gma500: implement backlight functionality for Cedartrail devices
Basically a straight cut/paste from the reference driver code then cleaned up a spot. Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/gma500/cdv_device.c')
-rw-r--r--drivers/gpu/drm/gma500/cdv_device.c115
1 files changed, 52 insertions, 63 deletions
diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c
index 62f9b735459b..726bfb7375fc 100644
--- a/drivers/gpu/drm/gma500/cdv_device.c
+++ b/drivers/gpu/drm/gma500/cdv_device.c
@@ -57,8 +57,7 @@ static int cdv_output_init(struct drm_device *dev)
57 cdv_intel_crt_init(dev, &dev_priv->mode_dev); 57 cdv_intel_crt_init(dev, &dev_priv->mode_dev);
58 cdv_intel_lvds_init(dev, &dev_priv->mode_dev); 58 cdv_intel_lvds_init(dev, &dev_priv->mode_dev);
59 59
60 /* These bits indicate HDMI not SDVO on CDV, but we don't yet support 60 /* These bits indicate HDMI not SDVO on CDV */
61 the HDMI interface */
62 if (REG_READ(SDVOB) & SDVO_DETECTED) 61 if (REG_READ(SDVOB) & SDVO_DETECTED)
63 cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOB); 62 cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOB);
64 if (REG_READ(SDVOC) & SDVO_DETECTED) 63 if (REG_READ(SDVOC) & SDVO_DETECTED)
@@ -69,76 +68,71 @@ static int cdv_output_init(struct drm_device *dev)
69#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE 68#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
70 69
71/* 70/*
72 * Poulsbo Backlight Interfaces 71 * Cedartrail Backlght Interfaces
73 */ 72 */
74 73
75#define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */
76#define BLC_PWM_FREQ_CALC_CONSTANT 32
77#define MHz 1000000
78
79#define PSB_BLC_PWM_PRECISION_FACTOR 10
80#define PSB_BLC_MAX_PWM_REG_FREQ 0xFFFE
81#define PSB_BLC_MIN_PWM_REG_FREQ 0x2
82
83#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
84#define PSB_BACKLIGHT_PWM_CTL_SHIFT (16)
85
86static int cdv_brightness;
87static struct backlight_device *cdv_backlight_device; 74static struct backlight_device *cdv_backlight_device;
88 75
89static int cdv_get_brightness(struct backlight_device *bd) 76static int cdv_backlight_combination_mode(struct drm_device *dev)
90{ 77{
91 /* return locally cached var instead of HW read (due to DPST etc.) */ 78 return REG_READ(BLC_PWM_CTL2) & PWM_LEGACY_MODE;
92 /* FIXME: ideally return actual value in case firmware fiddled with
93 it */
94 return cdv_brightness;
95} 79}
96 80
97 81static int cdv_get_brightness(struct backlight_device *bd)
98static int cdv_backlight_setup(struct drm_device *dev)
99{ 82{
100 struct drm_psb_private *dev_priv = dev->dev_private; 83 struct drm_device *dev = bl_get_data(bd);
101 unsigned long core_clock; 84 u32 val = REG_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
102 /* u32 bl_max_freq; */
103 /* unsigned long value; */
104 u16 bl_max_freq;
105 uint32_t value;
106 uint32_t blc_pwm_precision_factor;
107
108 /* get bl_max_freq and pol from dev_priv*/
109 if (!dev_priv->lvds_bl) {
110 dev_err(dev->dev, "Has no valid LVDS backlight info\n");
111 return -ENOENT;
112 }
113 bl_max_freq = dev_priv->lvds_bl->freq;
114 blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR;
115 85
116 core_clock = dev_priv->core_freq; 86 if (cdv_backlight_combination_mode(dev)) {
87 u8 lbpc;
117 88
118 value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT; 89 val &= ~1;
119 value *= blc_pwm_precision_factor; 90 pci_read_config_byte(dev->pdev, 0xF4, &lbpc);
120 value /= bl_max_freq; 91 val *= lbpc;
121 value /= blc_pwm_precision_factor; 92 }
93 return val;
94}
122 95
123 if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ || 96static u32 cdv_get_max_backlight(struct drm_device *dev)
124 value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ) 97{
125 return -ERANGE; 98 u32 max = REG_READ(BLC_PWM_CTL);
126 else { 99
127 /* FIXME */ 100 if (max == 0) {
101 DRM_DEBUG_KMS("LVDS Panel PWM value is 0!\n");
102 /* i915 does this, I believe which means that we should not
103 * smash PWM control as firmware will take control of it. */
104 return 1;
128 } 105 }
129 return 0; 106
107 max >>= 16;
108 if (cdv_backlight_combination_mode(dev))
109 max *= 0xff;
110 return max;
130} 111}
131 112
132static int cdv_set_brightness(struct backlight_device *bd) 113static int cdv_set_brightness(struct backlight_device *bd)
133{ 114{
115 struct drm_device *dev = bl_get_data(bd);
134 int level = bd->props.brightness; 116 int level = bd->props.brightness;
117 u32 blc_pwm_ctl;
135 118
136 /* Percentage 1-100% being valid */ 119 /* Percentage 1-100% being valid */
137 if (level < 1) 120 if (level < 1)
138 level = 1; 121 level = 1;
139 122
140 /*cdv_intel_lvds_set_brightness(dev, level); FIXME */ 123 if (cdv_backlight_combination_mode(dev)) {
141 cdv_brightness = level; 124 u32 max = cdv_get_max_backlight(dev);
125 u8 lbpc;
126
127 lbpc = level * 0xfe / max + 1;
128 level /= lbpc;
129
130 pci_write_config_byte(dev->pdev, 0xF4, lbpc);
131 }
132
133 blc_pwm_ctl = REG_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
134 REG_WRITE(BLC_PWM_CTL, (blc_pwm_ctl |
135 (level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
142 return 0; 136 return 0;
143} 137}
144 138
@@ -150,7 +144,6 @@ static const struct backlight_ops cdv_ops = {
150static int cdv_backlight_init(struct drm_device *dev) 144static int cdv_backlight_init(struct drm_device *dev)
151{ 145{
152 struct drm_psb_private *dev_priv = dev->dev_private; 146 struct drm_psb_private *dev_priv = dev->dev_private;
153 int ret;
154 struct backlight_properties props; 147 struct backlight_properties props;
155 148
156 memset(&props, 0, sizeof(struct backlight_properties)); 149 memset(&props, 0, sizeof(struct backlight_properties));
@@ -162,14 +155,9 @@ static int cdv_backlight_init(struct drm_device *dev)
162 if (IS_ERR(cdv_backlight_device)) 155 if (IS_ERR(cdv_backlight_device))
163 return PTR_ERR(cdv_backlight_device); 156 return PTR_ERR(cdv_backlight_device);
164 157
165 ret = cdv_backlight_setup(dev); 158 cdv_backlight_device->props.brightness =
166 if (ret < 0) { 159 cdv_get_brightness(cdv_backlight_device);
167 backlight_device_unregister(cdv_backlight_device); 160 cdv_backlight_device->props.max_brightness = cdv_get_max_brightness;
168 cdv_backlight_device = NULL;
169 return ret;
170 }
171 cdv_backlight_device->props.brightness = 100;
172 cdv_backlight_device->props.max_brightness = 100;
173 backlight_update_status(cdv_backlight_device); 161 backlight_update_status(cdv_backlight_device);
174 dev_priv->backlight_device = cdv_backlight_device; 162 dev_priv->backlight_device = cdv_backlight_device;
175 return 0; 163 return 0;
@@ -244,11 +232,12 @@ static void cdv_init_pm(struct drm_device *dev)
244static void cdv_errata(struct drm_device *dev) 232static void cdv_errata(struct drm_device *dev)
245{ 233{
246 /* Disable bonus launch. 234 /* Disable bonus launch.
247 * CPU and GPU competes for memory and display misses updates and flickers. 235 * CPU and GPU competes for memory and display misses updates and
248 * Worst with dual core, dual displays. 236 * flickers. Worst with dual core, dual displays.
249 * 237 *
250 * Fixes were done to Win 7 gfx driver to disable a feature called Bonus 238 * Fixes were done to Win 7 gfx driver to disable a feature called
251 * Launch to work around the issue, by degrading performance. 239 * Bonus Launch to work around the issue, by degrading
240 * performance.
252 */ 241 */
253 CDV_MSG_WRITE32(3, 0x30, 0x08027108); 242 CDV_MSG_WRITE32(3, 0x30, 0x08027108);
254} 243}