diff options
author | Alan Cox <alan@linux.intel.com> | 2012-05-03 10:06:05 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2012-05-03 11:28:04 -0400 |
commit | 9aba9d3a2ca42572c9c196e8be6cab59b7c078b6 (patch) | |
tree | 031eadf3606808d8018b8ba3f8ab1bec49c85c40 /drivers/gpu/drm/gma500 | |
parent | bb84977941ad85a5c0b9ff4fd5331913e31107c4 (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')
-rw-r--r-- | drivers/gpu/drm/gma500/cdv_device.c | 115 |
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 | |||
86 | static int cdv_brightness; | ||
87 | static struct backlight_device *cdv_backlight_device; | 74 | static struct backlight_device *cdv_backlight_device; |
88 | 75 | ||
89 | static int cdv_get_brightness(struct backlight_device *bd) | 76 | static 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 | 81 | static int cdv_get_brightness(struct backlight_device *bd) | |
98 | static 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 || | 96 | static 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 | ||
132 | static int cdv_set_brightness(struct backlight_device *bd) | 113 | static 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 = { | |||
150 | static int cdv_backlight_init(struct drm_device *dev) | 144 | static 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) | |||
244 | static void cdv_errata(struct drm_device *dev) | 232 | static 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 | } |