diff options
| -rw-r--r-- | drivers/gpu/drm/sti/sti_tvout.c | 92 |
1 files changed, 52 insertions, 40 deletions
diff --git a/drivers/gpu/drm/sti/sti_tvout.c b/drivers/gpu/drm/sti/sti_tvout.c index b8afe490356a..604e574d726e 100644 --- a/drivers/gpu/drm/sti/sti_tvout.c +++ b/drivers/gpu/drm/sti/sti_tvout.c | |||
| @@ -149,14 +149,15 @@ static void tvout_write(struct sti_tvout *tvout, u32 val, int offset) | |||
| 149 | * Set the clipping mode of a VIP | 149 | * Set the clipping mode of a VIP |
| 150 | * | 150 | * |
| 151 | * @tvout: tvout structure | 151 | * @tvout: tvout structure |
| 152 | * @reg: register to set | ||
| 152 | * @cr_r: | 153 | * @cr_r: |
| 153 | * @y_g: | 154 | * @y_g: |
| 154 | * @cb_b: | 155 | * @cb_b: |
| 155 | */ | 156 | */ |
| 156 | static void tvout_vip_set_color_order(struct sti_tvout *tvout, | 157 | static void tvout_vip_set_color_order(struct sti_tvout *tvout, int reg, |
| 157 | u32 cr_r, u32 y_g, u32 cb_b) | 158 | u32 cr_r, u32 y_g, u32 cb_b) |
| 158 | { | 159 | { |
| 159 | u32 val = tvout_read(tvout, TVO_VIP_HDMI); | 160 | u32 val = tvout_read(tvout, reg); |
| 160 | 161 | ||
| 161 | val &= ~(TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_R_SHIFT); | 162 | val &= ~(TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_R_SHIFT); |
| 162 | val &= ~(TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_G_SHIFT); | 163 | val &= ~(TVO_VIP_REORDER_MASK << TVO_VIP_REORDER_G_SHIFT); |
| @@ -165,52 +166,58 @@ static void tvout_vip_set_color_order(struct sti_tvout *tvout, | |||
| 165 | val |= y_g << TVO_VIP_REORDER_G_SHIFT; | 166 | val |= y_g << TVO_VIP_REORDER_G_SHIFT; |
| 166 | val |= cb_b << TVO_VIP_REORDER_B_SHIFT; | 167 | val |= cb_b << TVO_VIP_REORDER_B_SHIFT; |
| 167 | 168 | ||
| 168 | tvout_write(tvout, val, TVO_VIP_HDMI); | 169 | tvout_write(tvout, val, reg); |
| 169 | } | 170 | } |
| 170 | 171 | ||
| 171 | /** | 172 | /** |
| 172 | * Set the clipping mode of a VIP | 173 | * Set the clipping mode of a VIP |
| 173 | * | 174 | * |
| 174 | * @tvout: tvout structure | 175 | * @tvout: tvout structure |
| 176 | * @reg: register to set | ||
| 175 | * @range: clipping range | 177 | * @range: clipping range |
| 176 | */ | 178 | */ |
| 177 | static void tvout_vip_set_clip_mode(struct sti_tvout *tvout, u32 range) | 179 | static void tvout_vip_set_clip_mode(struct sti_tvout *tvout, int reg, u32 range) |
| 178 | { | 180 | { |
| 179 | u32 val = tvout_read(tvout, TVO_VIP_HDMI); | 181 | u32 val = tvout_read(tvout, reg); |
| 180 | 182 | ||
| 181 | val &= ~(TVO_VIP_CLIP_MASK << TVO_VIP_CLIP_SHIFT); | 183 | val &= ~(TVO_VIP_CLIP_MASK << TVO_VIP_CLIP_SHIFT); |
| 182 | val |= range << TVO_VIP_CLIP_SHIFT; | 184 | val |= range << TVO_VIP_CLIP_SHIFT; |
| 183 | tvout_write(tvout, val, TVO_VIP_HDMI); | 185 | tvout_write(tvout, val, reg); |
| 184 | } | 186 | } |
| 185 | 187 | ||
| 186 | /** | 188 | /** |
| 187 | * Set the rounded value of a VIP | 189 | * Set the rounded value of a VIP |
| 188 | * | 190 | * |
| 189 | * @tvout: tvout structure | 191 | * @tvout: tvout structure |
| 192 | * @reg: register to set | ||
| 190 | * @rnd: rounded val per component | 193 | * @rnd: rounded val per component |
| 191 | */ | 194 | */ |
| 192 | static void tvout_vip_set_rnd(struct sti_tvout *tvout, u32 rnd) | 195 | static void tvout_vip_set_rnd(struct sti_tvout *tvout, int reg, u32 rnd) |
| 193 | { | 196 | { |
| 194 | u32 val = tvout_read(tvout, TVO_VIP_HDMI); | 197 | u32 val = tvout_read(tvout, reg); |
| 195 | 198 | ||
| 196 | val &= ~(TVO_VIP_RND_MASK << TVO_VIP_RND_SHIFT); | 199 | val &= ~(TVO_VIP_RND_MASK << TVO_VIP_RND_SHIFT); |
| 197 | val |= rnd << TVO_VIP_RND_SHIFT; | 200 | val |= rnd << TVO_VIP_RND_SHIFT; |
| 198 | tvout_write(tvout, val, TVO_VIP_HDMI); | 201 | tvout_write(tvout, val, reg); |
| 199 | } | 202 | } |
| 200 | 203 | ||
| 201 | /** | 204 | /** |
| 202 | * Select the VIP input | 205 | * Select the VIP input |
| 203 | * | 206 | * |
| 204 | * @tvout: tvout structure | 207 | * @tvout: tvout structure |
| 208 | * @reg: register to set | ||
| 209 | * @main_path: main or auxiliary path | ||
| 210 | * @sel_input_logic_inverted: need to invert the logic | ||
| 205 | * @sel_input: selected_input (main/aux + conv) | 211 | * @sel_input: selected_input (main/aux + conv) |
| 206 | */ | 212 | */ |
| 207 | static void tvout_vip_set_sel_input(struct sti_tvout *tvout, | 213 | static void tvout_vip_set_sel_input(struct sti_tvout *tvout, |
| 214 | int reg, | ||
| 208 | bool main_path, | 215 | bool main_path, |
| 209 | bool sel_input_logic_inverted, | 216 | bool sel_input_logic_inverted, |
| 210 | enum sti_tvout_video_out_type video_out) | 217 | enum sti_tvout_video_out_type video_out) |
| 211 | { | 218 | { |
| 212 | u32 sel_input; | 219 | u32 sel_input; |
| 213 | u32 val = tvout_read(tvout, TVO_VIP_HDMI); | 220 | u32 val = tvout_read(tvout, reg); |
| 214 | 221 | ||
| 215 | if (main_path) | 222 | if (main_path) |
| 216 | sel_input = TVO_VIP_SEL_INPUT_MAIN; | 223 | sel_input = TVO_VIP_SEL_INPUT_MAIN; |
| @@ -232,22 +239,24 @@ static void tvout_vip_set_sel_input(struct sti_tvout *tvout, | |||
| 232 | 239 | ||
| 233 | val &= ~TVO_VIP_SEL_INPUT_MASK; | 240 | val &= ~TVO_VIP_SEL_INPUT_MASK; |
| 234 | val |= sel_input; | 241 | val |= sel_input; |
| 235 | tvout_write(tvout, val, TVO_VIP_HDMI); | 242 | tvout_write(tvout, val, reg); |
| 236 | } | 243 | } |
| 237 | 244 | ||
| 238 | /** | 245 | /** |
| 239 | * Select the input video signed or unsigned | 246 | * Select the input video signed or unsigned |
| 240 | * | 247 | * |
| 241 | * @tvout: tvout structure | 248 | * @tvout: tvout structure |
| 249 | * @reg: register to set | ||
| 242 | * @in_vid_signed: used video input format | 250 | * @in_vid_signed: used video input format |
| 243 | */ | 251 | */ |
| 244 | static void tvout_vip_set_in_vid_fmt(struct sti_tvout *tvout, u32 in_vid_fmt) | 252 | static void tvout_vip_set_in_vid_fmt(struct sti_tvout *tvout, |
| 253 | int reg, u32 in_vid_fmt) | ||
| 245 | { | 254 | { |
| 246 | u32 val = tvout_read(tvout, TVO_VIP_HDMI); | 255 | u32 val = tvout_read(tvout, reg); |
| 247 | 256 | ||
| 248 | val &= ~TVO_IN_FMT_SIGNED; | 257 | val &= ~TVO_IN_FMT_SIGNED; |
| 249 | val |= in_vid_fmt; | 258 | val |= in_vid_fmt; |
| 250 | tvout_write(tvout, val, TVO_MAIN_IN_VID_FORMAT); | 259 | tvout_write(tvout, val, reg); |
| 251 | } | 260 | } |
| 252 | 261 | ||
| 253 | /** | 262 | /** |
| @@ -261,6 +270,7 @@ static void tvout_hdmi_start(struct sti_tvout *tvout, bool main_path) | |||
| 261 | { | 270 | { |
| 262 | struct device_node *node = tvout->dev->of_node; | 271 | struct device_node *node = tvout->dev->of_node; |
| 263 | bool sel_input_logic_inverted = false; | 272 | bool sel_input_logic_inverted = false; |
| 273 | u32 tvo_in_vid_format; | ||
| 264 | 274 | ||
| 265 | dev_dbg(tvout->dev, "%s\n", __func__); | 275 | dev_dbg(tvout->dev, "%s\n", __func__); |
| 266 | 276 | ||
| @@ -268,33 +278,36 @@ static void tvout_hdmi_start(struct sti_tvout *tvout, bool main_path) | |||
| 268 | DRM_DEBUG_DRIVER("main vip for hdmi\n"); | 278 | DRM_DEBUG_DRIVER("main vip for hdmi\n"); |
| 269 | /* select the input sync for hdmi = VTG set 1 */ | 279 | /* select the input sync for hdmi = VTG set 1 */ |
| 270 | tvout_write(tvout, TVO_SYNC_MAIN_VTG_SET_1, TVO_HDMI_SYNC_SEL); | 280 | tvout_write(tvout, TVO_SYNC_MAIN_VTG_SET_1, TVO_HDMI_SYNC_SEL); |
| 281 | tvo_in_vid_format = TVO_MAIN_IN_VID_FORMAT; | ||
| 271 | } else { | 282 | } else { |
| 272 | DRM_DEBUG_DRIVER("aux vip for hdmi\n"); | 283 | DRM_DEBUG_DRIVER("aux vip for hdmi\n"); |
| 273 | /* select the input sync for hdmi = VTG set 1 */ | 284 | /* select the input sync for hdmi = VTG set 1 */ |
| 274 | tvout_write(tvout, TVO_SYNC_AUX_VTG_SET_1, TVO_HDMI_SYNC_SEL); | 285 | tvout_write(tvout, TVO_SYNC_AUX_VTG_SET_1, TVO_HDMI_SYNC_SEL); |
| 286 | tvo_in_vid_format = TVO_AUX_IN_VID_FORMAT; | ||
| 275 | } | 287 | } |
| 276 | 288 | ||
| 277 | /* set color channel order */ | 289 | /* set color channel order */ |
| 278 | tvout_vip_set_color_order(tvout, | 290 | tvout_vip_set_color_order(tvout, TVO_VIP_HDMI, |
| 279 | TVO_VIP_REORDER_CR_R_SEL, | 291 | TVO_VIP_REORDER_CR_R_SEL, |
| 280 | TVO_VIP_REORDER_Y_G_SEL, | 292 | TVO_VIP_REORDER_Y_G_SEL, |
| 281 | TVO_VIP_REORDER_CB_B_SEL); | 293 | TVO_VIP_REORDER_CB_B_SEL); |
| 282 | 294 | ||
| 283 | /* set clipping mode (Limited range RGB/Y) */ | 295 | /* set clipping mode (Limited range RGB/Y) */ |
| 284 | tvout_vip_set_clip_mode(tvout, TVO_VIP_CLIP_LIMITED_RANGE_RGB_Y); | 296 | tvout_vip_set_clip_mode(tvout, TVO_VIP_HDMI, |
| 297 | TVO_VIP_CLIP_LIMITED_RANGE_RGB_Y); | ||
| 285 | 298 | ||
| 286 | /* set round mode (rounded to 8-bit per component) */ | 299 | /* set round mode (rounded to 8-bit per component) */ |
| 287 | tvout_vip_set_rnd(tvout, TVO_VIP_RND_8BIT_ROUNDED); | 300 | tvout_vip_set_rnd(tvout, TVO_VIP_HDMI, TVO_VIP_RND_8BIT_ROUNDED); |
| 288 | 301 | ||
| 289 | if (of_device_is_compatible(node, "st,stih407-tvout")) { | 302 | if (of_device_is_compatible(node, "st,stih407-tvout")) { |
| 290 | /* set input video format */ | 303 | /* set input video format */ |
| 291 | tvout_vip_set_in_vid_fmt(tvout->regs + TVO_MAIN_IN_VID_FORMAT, | 304 | tvout_vip_set_in_vid_fmt(tvout, tvo_in_vid_format, |
| 292 | TVO_IN_FMT_SIGNED); | 305 | TVO_IN_FMT_SIGNED); |
| 293 | sel_input_logic_inverted = true; | 306 | sel_input_logic_inverted = true; |
| 294 | } | 307 | } |
| 295 | 308 | ||
| 296 | /* input selection */ | 309 | /* input selection */ |
| 297 | tvout_vip_set_sel_input(tvout, main_path, | 310 | tvout_vip_set_sel_input(tvout, TVO_VIP_HDMI, main_path, |
| 298 | sel_input_logic_inverted, STI_TVOUT_VIDEO_OUT_RGB); | 311 | sel_input_logic_inverted, STI_TVOUT_VIDEO_OUT_RGB); |
| 299 | } | 312 | } |
| 300 | 313 | ||
| @@ -309,48 +322,47 @@ static void tvout_hda_start(struct sti_tvout *tvout, bool main_path) | |||
| 309 | { | 322 | { |
| 310 | struct device_node *node = tvout->dev->of_node; | 323 | struct device_node *node = tvout->dev->of_node; |
| 311 | bool sel_input_logic_inverted = false; | 324 | bool sel_input_logic_inverted = false; |
| 325 | u32 tvo_in_vid_format; | ||
| 326 | int val; | ||
| 312 | 327 | ||
| 313 | dev_dbg(tvout->dev, "%s\n", __func__); | 328 | dev_dbg(tvout->dev, "%s\n", __func__); |
| 314 | 329 | ||
| 315 | if (!main_path) { | 330 | if (main_path) { |
| 316 | DRM_ERROR("HD Analog on aux not implemented\n"); | 331 | val = TVO_SYNC_MAIN_VTG_SET_2 << TVO_SYNC_HD_DCS_SHIFT; |
| 317 | return; | 332 | val |= TVO_SYNC_MAIN_VTG_SET_3; |
| 333 | tvout_write(tvout, val, TVO_HD_SYNC_SEL); | ||
| 334 | tvo_in_vid_format = TVO_MAIN_IN_VID_FORMAT; | ||
| 335 | } else { | ||
| 336 | val = TVO_SYNC_AUX_VTG_SET_2 << TVO_SYNC_HD_DCS_SHIFT; | ||
| 337 | val |= TVO_SYNC_AUX_VTG_SET_3; | ||
| 338 | tvout_write(tvout, val, TVO_HD_SYNC_SEL); | ||
| 339 | tvo_in_vid_format = TVO_AUX_IN_VID_FORMAT; | ||
| 318 | } | 340 | } |
| 319 | 341 | ||
| 320 | DRM_DEBUG_DRIVER("main vip for HDF\n"); | ||
| 321 | |||
| 322 | /* set color channel order */ | 342 | /* set color channel order */ |
| 323 | tvout_vip_set_color_order(tvout->regs + TVO_VIP_HDF, | 343 | tvout_vip_set_color_order(tvout, TVO_VIP_HDF, |
| 324 | TVO_VIP_REORDER_CR_R_SEL, | 344 | TVO_VIP_REORDER_CR_R_SEL, |
| 325 | TVO_VIP_REORDER_Y_G_SEL, | 345 | TVO_VIP_REORDER_Y_G_SEL, |
| 326 | TVO_VIP_REORDER_CB_B_SEL); | 346 | TVO_VIP_REORDER_CB_B_SEL); |
| 327 | 347 | ||
| 328 | /* set clipping mode (Limited range RGB/Y) */ | 348 | /* set clipping mode (EAV/SAV clipping) */ |
| 329 | tvout_vip_set_clip_mode(tvout->regs + TVO_VIP_HDF, | 349 | tvout_vip_set_clip_mode(tvout, TVO_VIP_HDF, TVO_VIP_CLIP_EAV_SAV); |
| 330 | TVO_VIP_CLIP_LIMITED_RANGE_CB_CR); | ||
| 331 | 350 | ||
| 332 | /* set round mode (rounded to 10-bit per component) */ | 351 | /* set round mode (rounded to 10-bit per component) */ |
| 333 | tvout_vip_set_rnd(tvout->regs + TVO_VIP_HDF, TVO_VIP_RND_10BIT_ROUNDED); | 352 | tvout_vip_set_rnd(tvout, TVO_VIP_HDF, TVO_VIP_RND_10BIT_ROUNDED); |
| 334 | 353 | ||
| 335 | if (of_device_is_compatible(node, "st,stih407-tvout")) { | 354 | if (of_device_is_compatible(node, "st,stih407-tvout")) { |
| 336 | /* set input video format */ | 355 | /* set input video format */ |
| 337 | tvout_vip_set_in_vid_fmt(tvout, TVO_IN_FMT_SIGNED); | 356 | tvout_vip_set_in_vid_fmt(tvout, |
| 357 | tvo_in_vid_format, TVO_IN_FMT_SIGNED); | ||
| 338 | sel_input_logic_inverted = true; | 358 | sel_input_logic_inverted = true; |
| 339 | } | 359 | } |
| 340 | 360 | ||
| 341 | /* Input selection */ | 361 | /* Input selection */ |
| 342 | tvout_vip_set_sel_input(tvout->regs + TVO_VIP_HDF, | 362 | tvout_vip_set_sel_input(tvout, TVO_VIP_HDF, main_path, |
| 343 | main_path, | ||
| 344 | sel_input_logic_inverted, | 363 | sel_input_logic_inverted, |
| 345 | STI_TVOUT_VIDEO_OUT_YUV); | 364 | STI_TVOUT_VIDEO_OUT_YUV); |
| 346 | 365 | ||
| 347 | /* select the input sync for HD analog = VTG set 3 | ||
| 348 | * and HD DCS = VTG set 2 */ | ||
| 349 | tvout_write(tvout, | ||
| 350 | (TVO_SYNC_MAIN_VTG_SET_2 << TVO_SYNC_HD_DCS_SHIFT) | ||
| 351 | | TVO_SYNC_MAIN_VTG_SET_3, | ||
| 352 | TVO_HD_SYNC_SEL); | ||
| 353 | |||
| 354 | /* power up HD DAC */ | 366 | /* power up HD DAC */ |
| 355 | tvout_write(tvout, 0, TVO_HD_DAC_CFG_OFF); | 367 | tvout_write(tvout, 0, TVO_HD_DAC_CFG_OFF); |
| 356 | } | 368 | } |
