aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/radeon/dce6_afmt.c9
-rw-r--r--drivers/gpu/drm/radeon/radeon.h3
-rw-r--r--drivers/gpu/drm/radeon/radeon_audio.c96
-rw-r--r--drivers/gpu/drm/radeon/radeon_audio.h26
-rw-r--r--drivers/gpu/drm/radeon/radeon_connectors.c8
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h1
6 files changed, 136 insertions, 7 deletions
diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c
index a97fb22ed06a..821f53ce3f65 100644
--- a/drivers/gpu/drm/radeon/dce6_afmt.c
+++ b/drivers/gpu/drm/radeon/dce6_afmt.c
@@ -23,9 +23,10 @@
23#include <linux/hdmi.h> 23#include <linux/hdmi.h>
24#include <drm/drmP.h> 24#include <drm/drmP.h>
25#include "radeon.h" 25#include "radeon.h"
26#include "radeon_audio.h"
26#include "sid.h" 27#include "sid.h"
27 28
28static u32 dce6_endpoint_rreg(struct radeon_device *rdev, 29u32 dce6_endpoint_rreg(struct radeon_device *rdev,
29 u32 block_offset, u32 reg) 30 u32 block_offset, u32 reg)
30{ 31{
31 unsigned long flags; 32 unsigned long flags;
@@ -39,7 +40,7 @@ static u32 dce6_endpoint_rreg(struct radeon_device *rdev,
39 return r; 40 return r;
40} 41}
41 42
42static void dce6_endpoint_wreg(struct radeon_device *rdev, 43void dce6_endpoint_wreg(struct radeon_device *rdev,
43 u32 block_offset, u32 reg, u32 v) 44 u32 block_offset, u32 reg, u32 v)
44{ 45{
45 unsigned long flags; 46 unsigned long flags;
@@ -54,10 +55,6 @@ static void dce6_endpoint_wreg(struct radeon_device *rdev,
54 spin_unlock_irqrestore(&rdev->end_idx_lock, flags); 55 spin_unlock_irqrestore(&rdev->end_idx_lock, flags);
55} 56}
56 57
57#define RREG32_ENDPOINT(block, reg) dce6_endpoint_rreg(rdev, (block), (reg))
58#define WREG32_ENDPOINT(block, reg, v) dce6_endpoint_wreg(rdev, (block), (reg), (v))
59
60
61static void dce6_afmt_get_connected_pins(struct radeon_device *rdev) 58static void dce6_afmt_get_connected_pins(struct radeon_device *rdev)
62{ 59{
63 int i; 60 int i;
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 4195e6cc4e52..d15e3c0c09f5 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -1757,6 +1757,9 @@ struct r600_audio {
1757 bool enabled; 1757 bool enabled;
1758 struct r600_audio_pin pin[RADEON_MAX_AFMT_BLOCKS]; 1758 struct r600_audio_pin pin[RADEON_MAX_AFMT_BLOCKS];
1759 int num_pins; 1759 int num_pins;
1760 struct radeon_audio_funcs *hdmi_funcs;
1761 struct radeon_audio_funcs *dp_funcs;
1762 struct radeon_audio_basic_funcs *funcs;
1760}; 1763};
1761 1764
1762/* 1765/*
diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c
index cc835e2e0de5..36174b6ca681 100644
--- a/drivers/gpu/drm/radeon/radeon_audio.c
+++ b/drivers/gpu/drm/radeon/radeon_audio.c
@@ -23,12 +23,18 @@
23 */ 23 */
24 24
25#include <drm/drmP.h> 25#include <drm/drmP.h>
26#include <drm/drm_crtc.h>
26#include "radeon.h" 27#include "radeon.h"
28#include "atom.h"
29#include "radeon_audio.h"
27 30
28void r600_audio_enable(struct radeon_device *rdev, struct r600_audio_pin *pin, 31void r600_audio_enable(struct radeon_device *rdev, struct r600_audio_pin *pin,
29 u8 enable_mask); 32 u8 enable_mask);
30void dce6_audio_enable(struct radeon_device *rdev, struct r600_audio_pin *pin, 33void dce6_audio_enable(struct radeon_device *rdev, struct r600_audio_pin *pin,
31 u8 enable_mask); 34 u8 enable_mask);
35u32 dce6_endpoint_rreg(struct radeon_device *rdev, u32 offset, u32 reg);
36void dce6_endpoint_wreg(struct radeon_device *rdev,
37 u32 offset, u32 reg, u32 v);
32 38
33static const u32 pin_offsets[7] = 39static const u32 pin_offsets[7] =
34{ 40{
@@ -41,6 +47,43 @@ static const u32 pin_offsets[7] =
41 (0x5e90 - 0x5e00), 47 (0x5e90 - 0x5e00),
42}; 48};
43 49
50static u32 radeon_audio_rreg(struct radeon_device *rdev, u32 offset, u32 reg)
51{
52 return RREG32(reg);
53}
54
55static void radeon_audio_wreg(struct radeon_device *rdev, u32 offset,
56 u32 reg, u32 v)
57{
58 WREG32(reg, v);
59}
60
61static struct radeon_audio_basic_funcs dce32_funcs = {
62 .endpoint_rreg = radeon_audio_rreg,
63 .endpoint_wreg = radeon_audio_wreg,
64};
65
66static struct radeon_audio_basic_funcs dce4_funcs = {
67 .endpoint_rreg = radeon_audio_rreg,
68 .endpoint_wreg = radeon_audio_wreg,
69};
70
71static struct radeon_audio_basic_funcs dce6_funcs = {
72 .endpoint_rreg = dce6_endpoint_rreg,
73 .endpoint_wreg = dce6_endpoint_wreg,
74};
75
76static void radeon_audio_interface_init(struct radeon_device *rdev)
77{
78 if (ASIC_IS_DCE6(rdev)) {
79 rdev->audio.funcs = &dce6_funcs;
80 } else if (ASIC_IS_DCE4(rdev)) {
81 rdev->audio.funcs = &dce4_funcs;
82 } else {
83 rdev->audio.funcs = &dce32_funcs;
84 }
85}
86
44static int radeon_audio_chipset_supported(struct radeon_device *rdev) 87static int radeon_audio_chipset_supported(struct radeon_device *rdev)
45{ 88{
46 return ASIC_IS_DCE2(rdev) && !ASIC_IS_NODCE(rdev); 89 return ASIC_IS_DCE2(rdev) && !ASIC_IS_NODCE(rdev);
@@ -79,12 +122,63 @@ int radeon_audio_init(struct radeon_device *rdev)
79 rdev->audio.pin[i].connected = false; 122 rdev->audio.pin[i].connected = false;
80 rdev->audio.pin[i].offset = pin_offsets[i]; 123 rdev->audio.pin[i].offset = pin_offsets[i];
81 rdev->audio.pin[i].id = i; 124 rdev->audio.pin[i].id = i;
82 /* disable audio. it will be set up later */ 125 }
126
127 radeon_audio_interface_init(rdev);
128
129 /* disable audio. it will be set up later */
130 for (i = 0; i < rdev->audio.num_pins; i++)
83 if (ASIC_IS_DCE6(rdev)) 131 if (ASIC_IS_DCE6(rdev))
84 dce6_audio_enable(rdev, &rdev->audio.pin[i], false); 132 dce6_audio_enable(rdev, &rdev->audio.pin[i], false);
85 else 133 else
86 r600_audio_enable(rdev, &rdev->audio.pin[i], false); 134 r600_audio_enable(rdev, &rdev->audio.pin[i], false);
135
136 return 0;
137}
138
139void radeon_audio_detect(struct drm_connector *connector,
140 enum drm_connector_status status)
141{
142 if (!connector || !connector->encoder)
143 return;
144
145 if (status == connector_status_connected) {
146 int sink_type;
147 struct radeon_device *rdev = connector->encoder->dev->dev_private;
148 struct radeon_connector *radeon_connector;
149 struct radeon_encoder *radeon_encoder =
150 to_radeon_encoder(connector->encoder);
151
152 if (!drm_detect_monitor_audio(radeon_connector_edid(connector))) {
153 radeon_encoder->audio = 0;
154 return;
155 }
156
157 radeon_connector = to_radeon_connector(connector);
158 sink_type = radeon_dp_getsinktype(radeon_connector);
159
160 if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort &&
161 sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT)
162 radeon_encoder->audio = rdev->audio.dp_funcs;
163 else
164 radeon_encoder->audio = rdev->audio.hdmi_funcs;
165 /* TODO: set up the sads, etc. and set the audio enable_mask */
166 } else {
167 /* TODO: reset the audio enable_mask */
87 } 168 }
169}
170
171u32 radeon_audio_endpoint_rreg(struct radeon_device *rdev, u32 offset, u32 reg)
172{
173 if (rdev->audio.funcs->endpoint_rreg)
174 return rdev->audio.funcs->endpoint_rreg(rdev, offset, reg);
88 175
89 return 0; 176 return 0;
90} 177}
178
179void radeon_audio_endpoint_wreg(struct radeon_device *rdev, u32 offset,
180 u32 reg, u32 v)
181{
182 if (rdev->audio.funcs->endpoint_wreg)
183 rdev->audio.funcs->endpoint_wreg(rdev, offset, reg, v);
184}
diff --git a/drivers/gpu/drm/radeon/radeon_audio.h b/drivers/gpu/drm/radeon/radeon_audio.h
index 8455fbdf97e4..e4b0b6437df7 100644
--- a/drivers/gpu/drm/radeon/radeon_audio.h
+++ b/drivers/gpu/drm/radeon/radeon_audio.h
@@ -21,9 +21,35 @@
21 * 21 *
22 * Authors: Slava Grigorev <slava.grigorev@amd.com> 22 * Authors: Slava Grigorev <slava.grigorev@amd.com>
23 */ 23 */
24
24#ifndef __RADEON_AUDIO_H__ 25#ifndef __RADEON_AUDIO_H__
25#define __RADEON_AUDIO_H__ 26#define __RADEON_AUDIO_H__
26 27
28#include <linux/types.h>
29
30#define RREG32_ENDPOINT(block, reg) \
31 radeon_audio_endpoint_rreg(rdev, (block), (reg))
32#define WREG32_ENDPOINT(block, reg, v) \
33 radeon_audio_endpoint_wreg(rdev, (block), (reg), (v))
34
35struct radeon_audio_basic_funcs
36{
37 u32 (*endpoint_rreg)(struct radeon_device *rdev, u32 offset, u32 reg);
38 void (*endpoint_wreg)(struct radeon_device *rdev,
39 u32 offset, u32 reg, u32 v);
40};
41
42struct radeon_audio_funcs
43{
44 /* TODO: add mode depended audio interface */
45};
46
27int radeon_audio_init(struct radeon_device *rdev); 47int radeon_audio_init(struct radeon_device *rdev);
48void radeon_audio_detect(struct drm_connector *connector,
49 enum drm_connector_status status);
50u32 radeon_audio_endpoint_rreg(struct radeon_device *rdev,
51 u32 offset, u32 reg);
52void radeon_audio_endpoint_wreg(struct radeon_device *rdev,
53 u32 offset, u32 reg, u32 v);
28 54
29#endif 55#endif
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 26baa9c05f6c..27def67cb6be 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -29,6 +29,7 @@
29#include <drm/drm_fb_helper.h> 29#include <drm/drm_fb_helper.h>
30#include <drm/radeon_drm.h> 30#include <drm/radeon_drm.h>
31#include "radeon.h" 31#include "radeon.h"
32#include "radeon_audio.h"
32#include "atom.h" 33#include "atom.h"
33 34
34#include <linux/pm_runtime.h> 35#include <linux/pm_runtime.h>
@@ -1332,6 +1333,9 @@ out:
1332 /* updated in get modes as well since we need to know if it's analog or digital */ 1333 /* updated in get modes as well since we need to know if it's analog or digital */
1333 radeon_connector_update_scratch_regs(connector, ret); 1334 radeon_connector_update_scratch_regs(connector, ret);
1334 1335
1336 if (radeon_audio != 0)
1337 radeon_audio_detect(connector, ret);
1338
1335exit: 1339exit:
1336 pm_runtime_mark_last_busy(connector->dev->dev); 1340 pm_runtime_mark_last_busy(connector->dev->dev);
1337 pm_runtime_put_autosuspend(connector->dev->dev); 1341 pm_runtime_put_autosuspend(connector->dev->dev);
@@ -1654,6 +1658,10 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
1654 } 1658 }
1655 1659
1656 radeon_connector_update_scratch_regs(connector, ret); 1660 radeon_connector_update_scratch_regs(connector, ret);
1661
1662 if (radeon_audio != 0)
1663 radeon_audio_detect(connector, ret);
1664
1657out: 1665out:
1658 pm_runtime_mark_last_busy(connector->dev->dev); 1666 pm_runtime_mark_last_busy(connector->dev->dev);
1659 pm_runtime_put_autosuspend(connector->dev->dev); 1667 pm_runtime_put_autosuspend(connector->dev->dev);
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 5135d02b7c1e..920a8be8abad 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -449,6 +449,7 @@ struct radeon_encoder {
449 int audio_polling_active; 449 int audio_polling_active;
450 bool is_ext_encoder; 450 bool is_ext_encoder;
451 u16 caps; 451 u16 caps;
452 struct radeon_audio_funcs *audio;
452}; 453};
453 454
454struct radeon_connector_atom_dig { 455struct radeon_connector_atom_dig {