Commit d02b0ffb authored by Dave Airlie's avatar Dave Airlie

Merge branch 'linux-4.13' of git://github.com/skeggsb/linux into drm-next

- HDMI stereoscopic support
- Rework of display code to properly support SOR pad macro routing on
>=GM20x GPUs
- Various other fixes/improvements.

* 'linux-4.13' of git://github.com/skeggsb/linux: (73 commits)
  drm/nouveau/disp/nv50-: avoid creating ORs that aren't present on HW
  drm/nouveau: use proper prototype in nouveau_pmops_runtime() definition
  drm/nouveau: Skip vga_fini on non-PCI device
  drm/nouveau/tegra: Don't leave GPU in reset
  drm/nouveau/tegra: Skip manual unpowergating when not necessary
  drm/nouveau/hwmon: Change permissions to numeric
  drm/nouveau/hwmon: expose the auto_point and pwm_min/max attrs
  drm/nouveau/hwmon: Remove old code, add .write/.read operations
  drm/nouveau/hwmon: Add nouveau_hwmon_ops structure with .is_visible/.read_string
  drm/nouveau/hwmon: Add config for all sensors and their settings
  drm/nouveau/disp/gm200-: allow non-identity mapping of SOR <-> macro links
  drm/nouveau/disp/nv50-: implement a common supervisor 3.0
  drm/nouveau/disp/nv50-: implement a common supervisor 2.2
  drm/nouveau/disp/nv50-: implement a common supervisor 2.1
  drm/nouveau/disp/nv50-: implement a common supervisor 2.0
  drm/nouveau/disp/nv50-: implement a common supervisor 1.0
  drm/nouveau/disp/nv50-gt21x: remove workaround for dp->tmds hotplug issues
  drm/nouveau/disp/dp: use new devinit script interpreter entry-point
  drm/nouveau/disp/dp: determine link bandwidth requirements from head state
  drm/nouveau/disp: introduce acquire/release display path methods
  ...
parents 4a525bad 7df1bb87
...@@ -169,18 +169,10 @@ static inline void ...@@ -169,18 +169,10 @@ static inline void
nouveau_bios_run_init_table(struct drm_device *dev, u16 table, nouveau_bios_run_init_table(struct drm_device *dev, u16 table,
struct dcb_output *outp, int crtc) struct dcb_output *outp, int crtc)
{ {
struct nouveau_drm *drm = nouveau_drm(dev); nvbios_init(&nvxx_bios(&nouveau_drm(dev)->client.device)->subdev, table,
struct nvkm_bios *bios = nvxx_bios(&drm->client.device); init.outp = outp;
struct nvbios_init init = { init.head = crtc;
.subdev = &bios->subdev, );
.bios = bios,
.offset = table,
.outp = outp,
.crtc = crtc,
.execute = 1,
};
nvbios_exec(&init);
} }
#endif #endif
...@@ -27,29 +27,25 @@ struct nv50_disp_scanoutpos_v0 { ...@@ -27,29 +27,25 @@ struct nv50_disp_scanoutpos_v0 {
struct nv50_disp_mthd_v1 { struct nv50_disp_mthd_v1 {
__u8 version; __u8 version;
#define NV50_DISP_MTHD_V1_DAC_PWR 0x10 #define NV50_DISP_MTHD_V1_ACQUIRE 0x01
#define NV50_DISP_MTHD_V1_RELEASE 0x02
#define NV50_DISP_MTHD_V1_DAC_LOAD 0x11 #define NV50_DISP_MTHD_V1_DAC_LOAD 0x11
#define NV50_DISP_MTHD_V1_SOR_PWR 0x20
#define NV50_DISP_MTHD_V1_SOR_HDA_ELD 0x21 #define NV50_DISP_MTHD_V1_SOR_HDA_ELD 0x21
#define NV50_DISP_MTHD_V1_SOR_HDMI_PWR 0x22 #define NV50_DISP_MTHD_V1_SOR_HDMI_PWR 0x22
#define NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT 0x23 #define NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT 0x23
#define NV50_DISP_MTHD_V1_SOR_DP_PWR 0x24
#define NV50_DISP_MTHD_V1_SOR_DP_MST_LINK 0x25 #define NV50_DISP_MTHD_V1_SOR_DP_MST_LINK 0x25
#define NV50_DISP_MTHD_V1_SOR_DP_MST_VCPI 0x26 #define NV50_DISP_MTHD_V1_SOR_DP_MST_VCPI 0x26
#define NV50_DISP_MTHD_V1_PIOR_PWR 0x30
__u8 method; __u8 method;
__u16 hasht; __u16 hasht;
__u16 hashm; __u16 hashm;
__u8 pad06[2]; __u8 pad06[2];
}; };
struct nv50_disp_dac_pwr_v0 { struct nv50_disp_acquire_v0 {
__u8 version; __u8 version;
__u8 state; __u8 or;
__u8 data; __u8 link;
__u8 vsync; __u8 pad03[5];
__u8 hsync;
__u8 pad05[3];
}; };
struct nv50_disp_dac_load_v0 { struct nv50_disp_dac_load_v0 {
...@@ -59,12 +55,6 @@ struct nv50_disp_dac_load_v0 { ...@@ -59,12 +55,6 @@ struct nv50_disp_dac_load_v0 {
__u32 data; __u32 data;
}; };
struct nv50_disp_sor_pwr_v0 {
__u8 version;
__u8 state;
__u8 pad02[6];
};
struct nv50_disp_sor_hda_eld_v0 { struct nv50_disp_sor_hda_eld_v0 {
__u8 version; __u8 version;
__u8 pad01[7]; __u8 pad01[7];
...@@ -76,7 +66,9 @@ struct nv50_disp_sor_hdmi_pwr_v0 { ...@@ -76,7 +66,9 @@ struct nv50_disp_sor_hdmi_pwr_v0 {
__u8 state; __u8 state;
__u8 max_ac_packet; __u8 max_ac_packet;
__u8 rekey; __u8 rekey;
__u8 pad04[4]; __u8 avi_infoframe_length;
__u8 vendor_infoframe_length;
__u8 pad06[2];
}; };
struct nv50_disp_sor_lvds_script_v0 { struct nv50_disp_sor_lvds_script_v0 {
...@@ -86,12 +78,6 @@ struct nv50_disp_sor_lvds_script_v0 { ...@@ -86,12 +78,6 @@ struct nv50_disp_sor_lvds_script_v0 {
__u8 pad04[4]; __u8 pad04[4];
}; };
struct nv50_disp_sor_dp_pwr_v0 {
__u8 version;
__u8 state;
__u8 pad02[6];
};
struct nv50_disp_sor_dp_mst_link_v0 { struct nv50_disp_sor_dp_mst_link_v0 {
__u8 version; __u8 version;
__u8 state; __u8 state;
...@@ -106,11 +92,4 @@ struct nv50_disp_sor_dp_mst_vcpi_v0 { ...@@ -106,11 +92,4 @@ struct nv50_disp_sor_dp_mst_vcpi_v0 {
__u16 pbn; __u16 pbn;
__u16 aligned_pbn; __u16 aligned_pbn;
}; };
struct nv50_disp_pior_pwr_v0 {
__u8 version;
__u8 state;
__u8 type;
__u8 pad03[5];
};
#endif #endif
...@@ -8,17 +8,15 @@ struct nvkm_disp { ...@@ -8,17 +8,15 @@ struct nvkm_disp {
const struct nvkm_disp_func *func; const struct nvkm_disp_func *func;
struct nvkm_engine engine; struct nvkm_engine engine;
struct nvkm_oproxy *client; struct list_head head;
struct list_head ior;
struct list_head outp; struct list_head outp;
struct list_head conn; struct list_head conn;
struct nvkm_event hpd; struct nvkm_event hpd;
struct nvkm_event vblank; struct nvkm_event vblank;
struct { struct nvkm_oproxy *client;
int nr;
} head;
}; };
int nv04_disp_new(struct nvkm_device *, int, struct nvkm_disp **); int nv04_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
...@@ -26,7 +24,9 @@ int nv50_disp_new(struct nvkm_device *, int, struct nvkm_disp **); ...@@ -26,7 +24,9 @@ int nv50_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
int g84_disp_new(struct nvkm_device *, int, struct nvkm_disp **); int g84_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
int gt200_disp_new(struct nvkm_device *, int, struct nvkm_disp **); int gt200_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
int g94_disp_new(struct nvkm_device *, int, struct nvkm_disp **); int g94_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
int mcp77_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
int gt215_disp_new(struct nvkm_device *, int, struct nvkm_disp **); int gt215_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
int mcp89_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
int gf119_disp_new(struct nvkm_device *, int, struct nvkm_disp **); int gf119_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
int gk104_disp_new(struct nvkm_device *, int, struct nvkm_disp **); int gk104_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
int gk110_disp_new(struct nvkm_device *, int, struct nvkm_disp **); int gk110_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
......
...@@ -3,19 +3,34 @@ ...@@ -3,19 +3,34 @@
struct nvbios_init { struct nvbios_init {
struct nvkm_subdev *subdev; struct nvkm_subdev *subdev;
struct nvkm_bios *bios; u32 offset;
u16 offset;
struct dcb_output *outp; struct dcb_output *outp;
int crtc; int or;
int link;
int head;
/* internal state used during parsing */ /* internal state used during parsing */
u8 execute; u8 execute;
u32 nested; u32 nested;
u16 repeat; u32 repeat;
u16 repend; u32 repend;
u32 ramcfg; u32 ramcfg;
}; };
#define nvbios_init(s,o,ARGS...) ({ \
struct nvbios_init init = { \
.subdev = (s), \
.offset = (o), \
.or = -1, \
.link = 0, \
.head = -1, \
.execute = 1, \
}; \
ARGS \
nvbios_exec(&init); \
})
int nvbios_exec(struct nvbios_init *); int nvbios_exec(struct nvbios_init *);
int nvbios_init(struct nvkm_subdev *, bool execute);
int nvbios_post(struct nvkm_subdev *, bool execute);
#endif #endif
...@@ -26,7 +26,6 @@ struct nvkm_timer { ...@@ -26,7 +26,6 @@ struct nvkm_timer {
u64 nvkm_timer_read(struct nvkm_timer *); u64 nvkm_timer_read(struct nvkm_timer *);
void nvkm_timer_alarm(struct nvkm_timer *, u32 nsec, struct nvkm_alarm *); void nvkm_timer_alarm(struct nvkm_timer *, u32 nsec, struct nvkm_alarm *);
void nvkm_timer_alarm_cancel(struct nvkm_timer *, struct nvkm_alarm *);
/* Delay based on GPU time (ie. PTIMER). /* Delay based on GPU time (ie. PTIMER).
* *
......
...@@ -1533,7 +1533,8 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, ...@@ -1533,7 +1533,8 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
if (conf & 0x100000) if (conf & 0x100000)
entry->i2c_upper_default = true; entry->i2c_upper_default = true;
entry->hasht = (entry->location << 4) | entry->type; entry->hasht = (entry->extdev << 8) | (entry->location << 4) |
entry->type;
entry->hashm = (entry->heads << 8) | (link << 6) | entry->or; entry->hashm = (entry->heads << 8) | (link << 6) | entry->or;
return true; return true;
} }
......
...@@ -1045,6 +1045,9 @@ nouveau_connector_mode_valid(struct drm_connector *connector, ...@@ -1045,6 +1045,9 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
return MODE_BAD; return MODE_BAD;
} }
if ((mode->flags & DRM_MODE_FLAG_3D_MASK) == DRM_MODE_FLAG_3D_FRAME_PACKING)
clock *= 2;
if (clock < min_clock) if (clock < min_clock)
return MODE_CLOCK_LOW; return MODE_CLOCK_LOW;
...@@ -1321,6 +1324,13 @@ nouveau_connector_create(struct drm_device *dev, int index) ...@@ -1321,6 +1324,13 @@ nouveau_connector_create(struct drm_device *dev, int index)
break; break;
} }
/* HDMI 3D support */
if ((disp->disp.oclass >= G82_DISP)
&& ((type == DRM_MODE_CONNECTOR_DisplayPort)
|| (type == DRM_MODE_CONNECTOR_eDP)
|| (type == DRM_MODE_CONNECTOR_HDMIA)))
connector->stereo_allowed = true;
/* defaults, will get overridden in detect() */ /* defaults, will get overridden in detect() */
connector->interlace_allowed = false; connector->interlace_allowed = false;
connector->doublescan_allowed = false; connector->doublescan_allowed = false;
......
...@@ -727,7 +727,7 @@ nouveau_pmops_thaw(struct device *dev) ...@@ -727,7 +727,7 @@ nouveau_pmops_thaw(struct device *dev)
} }
bool bool
nouveau_pmops_runtime() nouveau_pmops_runtime(void)
{ {
if (nouveau_runtime_pm == -1) if (nouveau_runtime_pm == -1)
return nouveau_is_optimus() || nouveau_is_v1_dsm(); return nouveau_is_optimus() || nouveau_is_v1_dsm();
......
...@@ -42,6 +42,7 @@ struct nouveau_encoder { ...@@ -42,6 +42,7 @@ struct nouveau_encoder {
struct dcb_output *dcb; struct dcb_output *dcb;
int or; int or;
int link;
struct i2c_adapter *i2c; struct i2c_adapter *i2c;
struct nvkm_i2c_aux *aux; struct nvkm_i2c_aux *aux;
......
This diff is collapsed.
...@@ -111,6 +111,10 @@ nouveau_vga_fini(struct nouveau_drm *drm) ...@@ -111,6 +111,10 @@ nouveau_vga_fini(struct nouveau_drm *drm)
struct drm_device *dev = drm->dev; struct drm_device *dev = drm->dev;
bool runtime = nouveau_pmops_runtime(); bool runtime = nouveau_pmops_runtime();
/* only relevant for PCI devices */
if (!dev->pdev)
return;
vga_client_register(dev->pdev, NULL, NULL, NULL); vga_client_register(dev->pdev, NULL, NULL, NULL);
if (pci_is_thunderbolt_attached(dev->pdev)) if (pci_is_thunderbolt_attached(dev->pdev))
......
This diff is collapsed.
...@@ -1257,7 +1257,7 @@ nvaa_chipset = { ...@@ -1257,7 +1257,7 @@ nvaa_chipset = {
.therm = g84_therm_new, .therm = g84_therm_new,
.timer = nv41_timer_new, .timer = nv41_timer_new,
.volt = nv40_volt_new, .volt = nv40_volt_new,
.disp = g94_disp_new, .disp = mcp77_disp_new,
.dma = nv50_dma_new, .dma = nv50_dma_new,
.fifo = g84_fifo_new, .fifo = g84_fifo_new,
.gr = gt200_gr_new, .gr = gt200_gr_new,
...@@ -1289,7 +1289,7 @@ nvac_chipset = { ...@@ -1289,7 +1289,7 @@ nvac_chipset = {
.therm = g84_therm_new, .therm = g84_therm_new,
.timer = nv41_timer_new, .timer = nv41_timer_new,
.volt = nv40_volt_new, .volt = nv40_volt_new,
.disp = g94_disp_new, .disp = mcp77_disp_new,
.dma = nv50_dma_new, .dma = nv50_dma_new,
.fifo = g84_fifo_new, .fifo = g84_fifo_new,
.gr = mcp79_gr_new, .gr = mcp79_gr_new,
...@@ -1323,7 +1323,7 @@ nvaf_chipset = { ...@@ -1323,7 +1323,7 @@ nvaf_chipset = {
.timer = nv41_timer_new, .timer = nv41_timer_new,
.volt = nv40_volt_new, .volt = nv40_volt_new,
.ce[0] = gt215_ce_new, .ce[0] = gt215_ce_new,
.disp = gt215_disp_new, .disp = mcp89_disp_new,
.dma = nv50_dma_new, .dma = nv50_dma_new,
.fifo = g84_fifo_new, .fifo = g84_fifo_new,
.gr = mcp89_gr_new, .gr = mcp89_gr_new,
......
...@@ -51,10 +51,12 @@ nvkm_device_tegra_power_up(struct nvkm_device_tegra *tdev) ...@@ -51,10 +51,12 @@ nvkm_device_tegra_power_up(struct nvkm_device_tegra *tdev)
reset_control_assert(tdev->rst); reset_control_assert(tdev->rst);
udelay(10); udelay(10);
if (!tdev->pdev->dev.pm_domain) {
ret = tegra_powergate_remove_clamping(TEGRA_POWERGATE_3D); ret = tegra_powergate_remove_clamping(TEGRA_POWERGATE_3D);
if (ret) if (ret)
goto err_clamp; goto err_clamp;
udelay(10); udelay(10);
}
reset_control_deassert(tdev->rst); reset_control_deassert(tdev->rst);
udelay(10); udelay(10);
...@@ -80,9 +82,6 @@ nvkm_device_tegra_power_down(struct nvkm_device_tegra *tdev) ...@@ -80,9 +82,6 @@ nvkm_device_tegra_power_down(struct nvkm_device_tegra *tdev)
{ {
int ret; int ret;
reset_control_assert(tdev->rst);
udelay(10);
clk_disable_unprepare(tdev->clk_pwr); clk_disable_unprepare(tdev->clk_pwr);
if (tdev->clk_ref) if (tdev->clk_ref)
clk_disable_unprepare(tdev->clk_ref); clk_disable_unprepare(tdev->clk_ref);
......
...@@ -4,7 +4,9 @@ nvkm-y += nvkm/engine/disp/nv50.o ...@@ -4,7 +4,9 @@ nvkm-y += nvkm/engine/disp/nv50.o
nvkm-y += nvkm/engine/disp/g84.o nvkm-y += nvkm/engine/disp/g84.o
nvkm-y += nvkm/engine/disp/g94.o nvkm-y += nvkm/engine/disp/g94.o
nvkm-y += nvkm/engine/disp/gt200.o nvkm-y += nvkm/engine/disp/gt200.o
nvkm-y += nvkm/engine/disp/mcp77.o
nvkm-y += nvkm/engine/disp/gt215.o nvkm-y += nvkm/engine/disp/gt215.o
nvkm-y += nvkm/engine/disp/mcp89.o
nvkm-y += nvkm/engine/disp/gf119.o nvkm-y += nvkm/engine/disp/gf119.o
nvkm-y += nvkm/engine/disp/gk104.o nvkm-y += nvkm/engine/disp/gk104.o
nvkm-y += nvkm/engine/disp/gk110.o nvkm-y += nvkm/engine/disp/gk110.o
...@@ -12,29 +14,41 @@ nvkm-y += nvkm/engine/disp/gm107.o ...@@ -12,29 +14,41 @@ nvkm-y += nvkm/engine/disp/gm107.o
nvkm-y += nvkm/engine/disp/gm200.o nvkm-y += nvkm/engine/disp/gm200.o
nvkm-y += nvkm/engine/disp/gp100.o nvkm-y += nvkm/engine/disp/gp100.o
nvkm-y += nvkm/engine/disp/gp102.o nvkm-y += nvkm/engine/disp/gp102.o
nvkm-y += nvkm/engine/disp/vga.o
nvkm-y += nvkm/engine/disp/outp.o nvkm-y += nvkm/engine/disp/head.o
nvkm-y += nvkm/engine/disp/outpdp.o nvkm-y += nvkm/engine/disp/headnv04.o
nvkm-y += nvkm/engine/disp/headnv50.o
nvkm-y += nvkm/engine/disp/headgf119.o
nvkm-y += nvkm/engine/disp/ior.o
nvkm-y += nvkm/engine/disp/dacnv50.o nvkm-y += nvkm/engine/disp/dacnv50.o
nvkm-y += nvkm/engine/disp/dacgf119.o
nvkm-y += nvkm/engine/disp/piornv50.o nvkm-y += nvkm/engine/disp/piornv50.o
nvkm-y += nvkm/engine/disp/sornv50.o nvkm-y += nvkm/engine/disp/sornv50.o
nvkm-y += nvkm/engine/disp/sorg84.o
nvkm-y += nvkm/engine/disp/sorg94.o nvkm-y += nvkm/engine/disp/sorg94.o
nvkm-y += nvkm/engine/disp/sormcp77.o
nvkm-y += nvkm/engine/disp/sorgt215.o
nvkm-y += nvkm/engine/disp/sormcp89.o
nvkm-y += nvkm/engine/disp/sorgf119.o nvkm-y += nvkm/engine/disp/sorgf119.o
nvkm-y += nvkm/engine/disp/sorgk104.o
nvkm-y += nvkm/engine/disp/sorgm107.o nvkm-y += nvkm/engine/disp/sorgm107.o
nvkm-y += nvkm/engine/disp/sorgm200.o nvkm-y += nvkm/engine/disp/sorgm200.o
nvkm-y += nvkm/engine/disp/dport.o
nvkm-y += nvkm/engine/disp/conn.o nvkm-y += nvkm/engine/disp/outp.o
nvkm-y += nvkm/engine/disp/dp.o
nvkm-y += nvkm/engine/disp/hdagt215.o nvkm-y += nvkm/engine/disp/hdagt215.o
nvkm-y += nvkm/engine/disp/hdagf119.o nvkm-y += nvkm/engine/disp/hdagf119.o
nvkm-y += nvkm/engine/disp/hdmi.o
nvkm-y += nvkm/engine/disp/hdmig84.o nvkm-y += nvkm/engine/disp/hdmig84.o
nvkm-y += nvkm/engine/disp/hdmigt215.o nvkm-y += nvkm/engine/disp/hdmigt215.o
nvkm-y += nvkm/engine/disp/hdmigf119.o nvkm-y += nvkm/engine/disp/hdmigf119.o
nvkm-y += nvkm/engine/disp/hdmigk104.o nvkm-y += nvkm/engine/disp/hdmigk104.o
nvkm-y += nvkm/engine/disp/vga.o nvkm-y += nvkm/engine/disp/conn.o
nvkm-y += nvkm/engine/disp/rootnv04.o nvkm-y += nvkm/engine/disp/rootnv04.o
nvkm-y += nvkm/engine/disp/rootnv50.o nvkm-y += nvkm/engine/disp/rootnv50.o
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
* Authors: Ben Skeggs * Authors: Ben Skeggs
*/ */
#include "dmacnv50.h" #include "dmacnv50.h"
#include "head.h"
#include "rootnv50.h" #include "rootnv50.h"
#include <core/client.h> #include <core/client.h>
...@@ -50,7 +51,7 @@ nv50_disp_base_new(const struct nv50_disp_dmac_func *func, ...@@ -50,7 +51,7 @@ nv50_disp_base_new(const struct nv50_disp_dmac_func *func,
nvif_ioctl(parent, "create disp base channel dma vers %d " nvif_ioctl(parent, "create disp base channel dma vers %d "
"pushbuf %016llx head %d\n", "pushbuf %016llx head %d\n",
args->v0.version, args->v0.pushbuf, args->v0.head); args->v0.version, args->v0.pushbuf, args->v0.head);
if (args->v0.head > disp->base.head.nr) if (!nvkm_head_find(&disp->base, args->v0.head))
return -EINVAL; return -EINVAL;
push = args->v0.pushbuf; push = args->v0.pushbuf;
head = args->v0.head; head = args->v0.head;
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "rootnv50.h" #include "rootnv50.h"
#include <core/client.h> #include <core/client.h>
#include <core/notify.h>
#include <core/ramht.h> #include <core/ramht.h>
#include <engine/dma.h> #include <engine/dma.h>
......
...@@ -30,9 +30,9 @@ ...@@ -30,9 +30,9 @@
#include <nvif/event.h> #include <nvif/event.h>
static int static int
nvkm_connector_hpd(struct nvkm_notify *notify) nvkm_conn_hpd(struct nvkm_notify *notify)
{ {
struct nvkm_connector *conn = container_of(notify, typeof(*conn), hpd); struct nvkm_conn *conn = container_of(notify, typeof(*conn), hpd);
struct nvkm_disp *disp = conn->disp; struct nvkm_disp *disp = conn->disp;
struct nvkm_gpio *gpio = disp->engine.subdev.device->gpio; struct nvkm_gpio *gpio = disp->engine.subdev.device->gpio;
const struct nvkm_gpio_ntfy_rep *line = notify->data; const struct nvkm_gpio_ntfy_rep *line = notify->data;
...@@ -52,21 +52,21 @@ nvkm_connector_hpd(struct nvkm_notify *notify) ...@@ -52,21 +52,21 @@ nvkm_connector_hpd(struct nvkm_notify *notify)
} }
void void
nvkm_connector_fini(struct nvkm_connector *conn) nvkm_conn_fini(struct nvkm_conn *conn)
{ {
nvkm_notify_put(&conn->hpd); nvkm_notify_put(&conn->hpd);
} }
void void
nvkm_connector_init(struct nvkm_connector *conn) nvkm_conn_init(struct nvkm_conn *conn)
{ {
nvkm_notify_get(&conn->hpd); nvkm_notify_get(&conn->hpd);
} }
void void
nvkm_connector_del(struct nvkm_connector **pconn) nvkm_conn_del(struct nvkm_conn **pconn)
{ {
struct nvkm_connector *conn = *pconn; struct nvkm_conn *conn = *pconn;
if (conn) { if (conn) {
nvkm_notify_fini(&conn->hpd); nvkm_notify_fini(&conn->hpd);
kfree(*pconn); kfree(*pconn);
...@@ -75,8 +75,8 @@ nvkm_connector_del(struct nvkm_connector **pconn) ...@@ -75,8 +75,8 @@ nvkm_connector_del(struct nvkm_connector **pconn)
} }
static void static void
nvkm_connector_ctor(struct nvkm_disp *disp, int index, nvkm_conn_ctor(struct nvkm_disp *disp, int index, struct nvbios_connE *info,
struct nvbios_connE *info, struct nvkm_connector *conn) struct nvkm_conn *conn)
{ {
static const u8 hpd[] = { 0x07, 0x08, 0x51, 0x52, 0x5e, 0x5f, 0x60 }; static const u8 hpd[] = { 0x07, 0x08, 0x51, 0x52, 0x5e, 0x5f, 0x60 };
struct nvkm_gpio *gpio = disp->engine.subdev.device->gpio; struct nvkm_gpio *gpio = disp->engine.subdev.device->gpio;
...@@ -105,7 +105,7 @@ nvkm_connector_ctor(struct nvkm_disp *disp, int index, ...@@ -105,7 +105,7 @@ nvkm_connector_ctor(struct nvkm_disp *disp, int index,
return; return;
} }
ret = nvkm_notify_init(NULL, &gpio->event, nvkm_connector_hpd, ret = nvkm_notify_init(NULL, &gpio->event, nvkm_conn_hpd,
true, &(struct nvkm_gpio_ntfy_req) { true, &(struct nvkm_gpio_ntfy_req) {
.mask = NVKM_GPIO_TOGGLED, .mask = NVKM_GPIO_TOGGLED,
.line = func.line, .line = func.line,
...@@ -122,11 +122,11 @@ nvkm_connector_ctor(struct nvkm_disp *disp, int index, ...@@ -122,11 +122,11 @@ nvkm_connector_ctor(struct nvkm_disp *disp, int index,
} }
int int
nvkm_connector_new(struct nvkm_disp *disp, int index, nvkm_conn_new(struct nvkm_disp *disp, int index, struct nvbios_connE *info,
struct nvbios_connE *info, struct nvkm_connector **pconn) struct nvkm_conn **pconn)
{ {
if (!(*pconn = kzalloc(sizeof(**pconn), GFP_KERNEL))) if (!(*pconn = kzalloc(sizeof(**pconn), GFP_KERNEL)))
return -ENOMEM; return -ENOMEM;
nvkm_connector_ctor(disp, index, info, *pconn); nvkm_conn_ctor(disp, index, info, *pconn);
return 0; return 0;
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
#include <subdev/bios.h> #include <subdev/bios.h>
#include <subdev/bios/conn.h> #include <subdev/bios/conn.h>
struct nvkm_connector { struct nvkm_conn {
struct nvkm_disp *disp; struct nvkm_disp *disp;
int index; int index;
struct nvbios_connE info; struct nvbios_connE info;
...@@ -16,14 +16,14 @@ struct nvkm_connector { ...@@ -16,14 +16,14 @@ struct nvkm_connector {
struct list_head head; struct list_head head;
}; };
int nvkm_connector_new(struct nvkm_disp *, int index, struct nvbios_connE *, int nvkm_conn_new(struct nvkm_disp *, int index, struct nvbios_connE *,
struct nvkm_connector **); struct nvkm_conn **);
void nvkm_connector_del(struct nvkm_connector **); void nvkm_conn_del(struct nvkm_conn **);
void nvkm_connector_init(struct nvkm_connector *); void nvkm_conn_init(struct nvkm_conn *);
void nvkm_connector_fini(struct nvkm_connector *); void nvkm_conn_fini(struct nvkm_conn *);
#define CONN_MSG(c,l,f,a...) do { \ #define CONN_MSG(c,l,f,a...) do { \
struct nvkm_connector *_conn = (c); \ struct nvkm_conn *_conn = (c); \
nvkm_##l(&_conn->disp->engine.subdev, "conn %02x:%02x%02x: "f"\n", \ nvkm_##l(&_conn->disp->engine.subdev, "conn %02x:%02x%02x: "f"\n", \
_conn->index, _conn->info.location, _conn->info.type, ##a); \ _conn->index, _conn->info.location, _conn->info.type, ##a); \
} while(0) } while(0)
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
* Authors: Ben Skeggs * Authors: Ben Skeggs
*/ */
#include "channv50.h" #include "channv50.h"
#include "head.h"
#include "rootnv50.h" #include "rootnv50.h"
#include <core/client.h> #include <core/client.h>
...@@ -48,7 +49,7 @@ nv50_disp_curs_new(const struct nv50_disp_chan_func *func, ...@@ -48,7 +49,7 @@ nv50_disp_curs_new(const struct nv50_disp_chan_func *func,
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
nvif_ioctl(parent, "create disp cursor vers %d head %d\n", nvif_ioctl(parent, "create disp cursor vers %d head %d\n",
args->v0.version, args->v0.head); args->v0.version, args->v0.head);
if (args->v0.head > disp->base.head.nr) if (!nvkm_head_find(&disp->base, args->v0.head))
return -EINVAL; return -EINVAL;
head = args->v0.head; head = args->v0.head;
} else } else
......
/*
* Copyright 2017 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "ior.h"
static void
gf119_dac_clock(struct nvkm_ior *dac)
{
struct nvkm_device *device = dac->disp->engine.subdev.device;
const u32 doff = nv50_ior_base(dac);
nvkm_mask(device, 0x612280 + doff, 0x07070707, 0x00000000);
}
static void
gf119_dac_state(struct nvkm_ior *dac, struct nvkm_ior_state *state)
{
struct nvkm_device *device = dac->disp->engine.subdev.device;
const u32 coff = (state == &dac->asy) * 0x20000 + dac->id * 0x20;
u32 ctrl = nvkm_rd32(device, 0x640180 + coff);
state->proto_evo = (ctrl & 0x00000f00) >> 8;
switch (state->proto_evo) {
case 0: state->proto = CRT; break;
default:
state->proto = UNKNOWN;
break;
}
state->head = ctrl & 0x0000000f;
}
static const struct nvkm_ior_func
gf119_dac = {
.state = gf119_dac_state,
.power = nv50_dac_power,
.sense = nv50_dac_sense,
.clock = gf119_dac_clock,
};
int
gf119_dac_new(struct nvkm_disp *disp, int id)
{
struct nvkm_device *device = disp->engine.subdev.device;
if (!(nvkm_rd32(device, 0x612004) & (0x00000010 << id)))
return 0;
return nvkm_ior_new_(&gf119_dac, disp, DAC, id);
}
...@@ -21,106 +21,96 @@ ...@@ -21,106 +21,96 @@
* *
* Authors: Ben Skeggs * Authors: Ben Skeggs
*/ */
#include "nv50.h" #include "ior.h"
#include "outp.h"
#include <core/client.h>
#include <subdev/timer.h> #include <subdev/timer.h>
#include <nvif/cl5070.h> static void
#include <nvif/unpack.h> nv50_dac_clock(struct nvkm_ior *dac)
int
nv50_dac_power(NV50_DISP_MTHD_V1)
{ {
struct nvkm_device *device = disp->base.engine.subdev.device; struct nvkm_device *device = dac->disp->engine.subdev.device;
const u32 doff = outp->or * 0x800; const u32 doff = nv50_ior_base(dac);
union { nvkm_mask(device, 0x614280 + doff, 0x07070707, 0x00000000);
struct nv50_disp_dac_pwr_v0 v0;
} *args = data;
u32 stat;
int ret = -ENOSYS;
nvif_ioctl(object, "disp dac pwr size %d\n", size);
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
nvif_ioctl(object, "disp dac pwr vers %d state %d data %d "
"vsync %d hsync %d\n",
args->v0.version, args->v0.state, args->v0.data,
args->v0.vsync, args->v0.hsync);
stat = 0x00000040 * !args->v0.state;
stat |= 0x00000010 * !args->v0.data;
stat |= 0x00000004 * !args->v0.vsync;
stat |= 0x00000001 * !args->v0.hsync;
} else
return ret;
nvkm_msec(device, 2000,
if (!(nvkm_rd32(device, 0x61a004 + doff) & 0x80000000))
break;
);
nvkm_mask(device, 0x61a004 + doff, 0xc000007f, 0x80000000 | stat);
nvkm_msec(device, 2000,
if (!(nvkm_rd32(device, 0x61a004 + doff) & 0x80000000))
break;
);
return 0;
} }
int int
nv50_dac_sense(NV50_DISP_MTHD_V1) nv50_dac_sense(struct nvkm_ior *dac, u32 loadval)
{ {
struct nvkm_subdev *subdev = &disp->base.engine.subdev; struct nvkm_device *device = dac->disp->engine.subdev.device;
struct nvkm_device *device = subdev->device; const u32 doff = nv50_ior_base(dac);
union {
struct nv50_disp_dac_load_v0 v0;
} *args = data;
const u32 doff = outp->or * 0x800;
u32 loadval;
int ret = -ENOSYS;
nvif_ioctl(object, "disp dac load size %d\n", size);
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
nvif_ioctl(object, "disp dac load vers %d data %08x\n",
args->v0.version, args->v0.data);
if (args->v0.data & 0xfff00000)
return -EINVAL;
loadval = args->v0.data;
} else
return ret;
nvkm_mask(device, 0x61a004 + doff, 0x807f0000, 0x80150000); dac->func->power(dac, false, true, false, false, false);
nvkm_msec(device, 2000,
if (!(nvkm_rd32(device, 0x61a004 + doff) & 0x80000000))
break;
);
nvkm_wr32(device, 0x61a00c + doff, 0x00100000 | loadval); nvkm_wr32(device, 0x61a00c + doff, 0x00100000 | loadval);
mdelay(9); mdelay(9);
udelay(500); udelay(500);
loadval = nvkm_mask(device, 0x61a00c + doff, 0xffffffff, 0x00000000); loadval = nvkm_mask(device, 0x61a00c + doff, 0xffffffff, 0x00000000);
nvkm_mask(device, 0x61a004 + doff, 0x807f0000, 0x80550000); dac->func->power(dac, false, false, false, false, false);
if (!(loadval & 0x80000000))
return -ETIMEDOUT;
return (loadval & 0x38000000) >> 27;
}
static void
nv50_dac_power_wait(struct nvkm_device *device, const u32 doff)
{
nvkm_msec(device, 2000, nvkm_msec(device, 2000,
if (!(nvkm_rd32(device, 0x61a004 + doff) & 0x80000000)) if (!(nvkm_rd32(device, 0x61a004 + doff) & 0x80000000))
break; break;
); );
}
nvkm_debug(subdev, "DAC%d sense: %08x\n", outp->or, loadval); void
if (!(loadval & 0x80000000)) nv50_dac_power(struct nvkm_ior *dac, bool normal, bool pu,
return -ETIMEDOUT; bool data, bool vsync, bool hsync)
{
struct nvkm_device *device = dac->disp->engine.subdev.device;
const u32 doff = nv50_ior_base(dac);
const u32 shift = normal ? 0 : 16;
const u32 state = 0x80000000 | (0x00000040 * ! pu |
0x00000010 * ! data |
0x00000004 * ! vsync |
0x00000001 * ! hsync) << shift;
const u32 field = 0xc0000000 | (0x00000055 << shift);
args->v0.load = (loadval & 0x38000000) >> 27; nv50_dac_power_wait(device, doff);
return 0; nvkm_mask(device, 0x61a004 + doff, field, state);
nv50_dac_power_wait(device, doff);
} }
static const struct nvkm_output_func static void
nv50_dac_output_func = { nv50_dac_state(struct nvkm_ior *dac, struct nvkm_ior_state *state)
{
struct nvkm_device *device = dac->disp->engine.subdev.device;
const u32 coff = dac->id * 8 + (state == &dac->arm) * 4;
u32 ctrl = nvkm_rd32(device, 0x610b58 + coff);
state->proto_evo = (ctrl & 0x00000f00) >> 8;
switch (state->proto_evo) {
case 0: state->proto = CRT; break;
default:
state->proto = UNKNOWN;
break;
}
state->head = ctrl & 0x00000003;
}
static const struct nvkm_ior_func
nv50_dac = {
.state = nv50_dac_state,
.power = nv50_dac_power,
.sense = nv50_dac_sense,
.clock = nv50_dac_clock,
}; };
int int
nv50_dac_output_new(struct nvkm_disp *disp, int index, nv50_dac_new(struct nvkm_disp *disp, int id)
struct dcb_output *dcbE, struct nvkm_output **poutp)
{ {
return nvkm_output_new_(&nv50_dac_output_func, disp, struct nvkm_device *device = disp->engine.subdev.device;
index, dcbE, poutp); if (!(nvkm_rd32(device, 0x610184) & (0x00100000 << id)))
return 0;
return nvkm_ior_new_(&nv50_dac, disp, DAC, id);
} }
This diff is collapsed.
#ifndef __NVKM_DISP_DPORT_H__ #ifndef __NVKM_DISP_DP_H__
#define __NVKM_DISP_DPORT_H__ #define __NVKM_DISP_DP_H__
struct nvkm_output_dp; #define nvkm_dp(p) container_of((p), struct nvkm_dp, outp)
#include "outp.h"
#include <core/notify.h>
#include <subdev/bios.h>
#include <subdev/bios/dp.h>
struct nvkm_dp {
union {
struct nvkm_outp base;
struct nvkm_outp outp;
};
struct nvbios_dpout info;
u8 version;
struct nvkm_i2c_aux *aux;
struct nvkm_notify hpd;
bool present;
u8 dpcd[16];
struct mutex mutex;
struct {
atomic_t done;
bool mst;
} lt;
};
int nvkm_dp_new(struct nvkm_disp *, int index, struct dcb_output *,
struct nvkm_outp **);
/* DPCD Receiver Capabilities */ /* DPCD Receiver Capabilities */
#define DPCD_RC00_DPCD_REV 0x00000 #define DPCD_RC00_DPCD_REV 0x00000
...@@ -76,6 +106,4 @@ struct nvkm_output_dp; ...@@ -76,6 +106,4 @@ struct nvkm_output_dp;
#define DPCD_SC00_SET_POWER 0x03 #define DPCD_SC00_SET_POWER 0x03
#define DPCD_SC00_SET_POWER_D0 0x01 #define DPCD_SC00_SET_POWER_D0 0x01
#define DPCD_SC00_SET_POWER_D3 0x03 #define DPCD_SC00_SET_POWER_D3 0x03
void nvkm_dp_train(struct nvkm_output_dp *);
#endif #endif
This diff is collapsed.
...@@ -22,30 +22,20 @@ ...@@ -22,30 +22,20 @@
* Authors: Ben Skeggs * Authors: Ben Skeggs
*/ */
#include "nv50.h" #include "nv50.h"
#include "head.h"
#include "ior.h"
#include "rootnv50.h" #include "rootnv50.h"
static const struct nv50_disp_func static const struct nv50_disp_func
g84_disp = { g84_disp = {
.intr = nv50_disp_intr, .intr = nv50_disp_intr,
.uevent = &nv50_disp_chan_uevent, .uevent = &nv50_disp_chan_uevent,
.super = nv50_disp_intr_supervisor, .super = nv50_disp_super,
.root = &g84_disp_root_oclass, .root = &g84_disp_root_oclass,
.head.vblank_init = nv50_disp_vblank_init, .head.new = nv50_head_new,
.head.vblank_fini = nv50_disp_vblank_fini, .dac = { .nr = 3, .new = nv50_dac_new },
.head.scanoutpos = nv50_disp_root_scanoutpos, .sor = { .nr = 2, .new = g84_sor_new },
.outp.internal.crt = nv50_dac_output_new, .pior = { .nr = 3, .new = nv50_pior_new },
.outp.internal.tmds = nv50_sor_output_new,
.outp.internal.lvds = nv50_sor_output_new,
.outp.external.tmds = nv50_pior_output_new,
.outp.external.dp = nv50_pior_dp_new,
.dac.nr = 3,
.dac.power = nv50_dac_power,
.dac.sense = nv50_dac_sense,
.sor.nr = 2,
.sor.power = nv50_sor_power,
.sor.hdmi = g84_hdmi_ctrl,
.pior.nr = 3,
.pior.power = nv50_pior_power,
}; };
int int
......
...@@ -22,31 +22,20 @@ ...@@ -22,31 +22,20 @@
* Authors: Ben Skeggs * Authors: Ben Skeggs
*/ */
#include "nv50.h" #include "nv50.h"
#include "head.h"
#include "ior.h"
#include "rootnv50.h" #include "rootnv50.h"
static const struct nv50_disp_func static const struct nv50_disp_func
g94_disp = { g94_disp = {
.intr = nv50_disp_intr, .intr = nv50_disp_intr,
.uevent = &nv50_disp_chan_uevent, .uevent = &nv50_disp_chan_uevent,
.super = nv50_disp_intr_supervisor, .super = nv50_disp_super,
.root = &g94_disp_root_oclass, .root = &g94_disp_root_oclass,
.head.vblank_init = nv50_disp_vblank_init, .head.new = nv50_head_new,
.head.vblank_fini = nv50_disp_vblank_fini, .dac = { .nr = 3, .new = nv50_dac_new },
.head.scanoutpos = nv50_disp_root_scanoutpos, .sor = { .nr = 4, .new = g94_sor_new },
.outp.internal.crt = nv50_dac_output_new, .pior = { .nr = 3, .new = nv50_pior_new },
.outp.internal.tmds = nv50_sor_output_new,
.outp.internal.lvds = nv50_sor_output_new,
.outp.internal.dp = g94_sor_dp_new,
.outp.external.tmds = nv50_pior_output_new,
.outp.external.dp = nv50_pior_dp_new,
.dac.nr = 3,
.dac.power = nv50_dac_power,
.dac.sense = nv50_dac_sense,
.sor.nr = 4,
.sor.power = nv50_sor_power,
.sor.hdmi = g84_hdmi_ctrl,
.pior.nr = 3,
.pior.power = nv50_pior_power,
}; };
int int
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
* Authors: Ben Skeggs * Authors: Ben Skeggs
*/ */
#include "nv50.h" #include "nv50.h"
#include "head.h"
#include "ior.h"
#include "rootnv50.h" #include "rootnv50.h"
static const struct nv50_disp_func static const struct nv50_disp_func
...@@ -29,22 +31,11 @@ gk104_disp = { ...@@ -29,22 +31,11 @@ gk104_disp = {
.intr = gf119_disp_intr, .intr = gf119_disp_intr,
.intr_error = gf119_disp_intr_error, .intr_error = gf119_disp_intr_error,
.uevent = &gf119_disp_chan_uevent, .uevent = &gf119_disp_chan_uevent,
.super = gf119_disp_intr_supervisor, .super = gf119_disp_super,
.root = &gk104_disp_root_oclass, .root = &gk104_disp_root_oclass,
.head.vblank_init = gf119_disp_vblank_init, .head.new = gf119_head_new,
.head.vblank_fini = gf119_disp_vblank_fini, .dac = { .nr = 3, .new = gf119_dac_new },
.head.scanoutpos = gf119_disp_root_scanoutpos, .sor = { .nr = 4, .new = gk104_sor_new },
.outp.internal.crt = nv50_dac_output_new,
.outp.internal.tmds = nv50_sor_output_new,
.outp.internal.lvds = nv50_sor_output_new,
.outp.internal.dp = gf119_sor_dp_new,
.dac.nr = 3,
.dac.power = nv50_dac_power,
.dac.sense = nv50_dac_sense,
.sor.nr = 4,
.sor.power = nv50_sor_power,
.sor.hda_eld = gf119_hda_eld,
.sor.hdmi = gk104_hdmi_ctrl,
}; };
int int
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
* Authors: Ben Skeggs * Authors: Ben Skeggs
*/ */
#include "nv50.h" #include "nv50.h"
#include "head.h"
#include "ior.h"
#include "rootnv50.h" #include "rootnv50.h"
static const struct nv50_disp_func static const struct nv50_disp_func
...@@ -29,22 +31,11 @@ gk110_disp = { ...@@ -29,22 +31,11 @@ gk110_disp = {
.intr = gf119_disp_intr, .intr = gf119_disp_intr,
.intr_error = gf119_disp_intr_error, .intr_error = gf119_disp_intr_error,
.uevent = &gf119_disp_chan_uevent, .uevent = &gf119_disp_chan_uevent,
.super = gf119_disp_intr_supervisor, .super = gf119_disp_super,
.root = &gk110_disp_root_oclass, .root = &gk110_disp_root_oclass,
.head.vblank_init = gf119_disp_vblank_init, .head.new = gf119_head_new,
.head.vblank_fini = gf119_disp_vblank_fini, .dac = { .nr = 3, .new = gf119_dac_new },
.head.scanoutpos = gf119_disp_root_scanoutpos, .sor = { .nr = 4, .new = gk104_sor_new },
.outp.internal.crt = nv50_dac_output_new,
.outp.internal.tmds = nv50_sor_output_new,
.outp.internal.lvds = nv50_sor_output_new,
.outp.internal.dp = gf119_sor_dp_new,
.dac.nr = 3,
.dac.power = nv50_dac_power,
.dac.sense = nv50_dac_sense,
.sor.nr = 4,
.sor.power = nv50_sor_power,
.sor.hda_eld = gf119_hda_eld,
.sor.hdmi = gk104_hdmi_ctrl,
}; };
int int
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
* Authors: Ben Skeggs * Authors: Ben Skeggs
*/ */
#include "nv50.h" #include "nv50.h"
#include "head.h"
#include "ior.h"
#include "rootnv50.h" #include "rootnv50.h"
static const struct nv50_disp_func static const struct nv50_disp_func
...@@ -29,22 +31,11 @@ gm107_disp = { ...@@ -29,22 +31,11 @@ gm107_disp = {
.intr = gf119_disp_intr, .intr = gf119_disp_intr,
.intr_error = gf119_disp_intr_error, .intr_error = gf119_disp_intr_error,
.uevent = &gf119_disp_chan_uevent, .uevent = &gf119_disp_chan_uevent,
.super = gf119_disp_intr_supervisor, .super = gf119_disp_super,
.root = &gm107_disp_root_oclass, .root = &gm107_disp_root_oclass,
.head.vblank_init = gf119_disp_vblank_init, .head.new = gf119_head_new,
.head.vblank_fini = gf119_disp_vblank_fini, .dac = { .nr = 3, .new = gf119_dac_new },
.head.scanoutpos = gf119_disp_root_scanoutpos, .sor = { .nr = 4, .new = gm107_sor_new },
.outp.internal.crt = nv50_dac_output_new,
.outp.internal.tmds = nv50_sor_output_new,
.outp.internal.lvds = nv50_sor_output_new,
.outp.internal.dp = gm107_sor_dp_new,
.dac.nr = 3,
.dac.power = nv50_dac_power,
.dac.sense = nv50_dac_sense,
.sor.nr = 4,
.sor.power = nv50_sor_power,
.sor.hda_eld = gf119_hda_eld,
.sor.hdmi = gk104_hdmi_ctrl,
}; };
int int
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
* Authors: Ben Skeggs * Authors: Ben Skeggs
*/ */
#include "nv50.h" #include "nv50.h"
#include "head.h"
#include "ior.h"
#include "rootnv50.h" #include "rootnv50.h"
static const struct nv50_disp_func static const struct nv50_disp_func
...@@ -29,23 +31,11 @@ gm200_disp = { ...@@ -29,23 +31,11 @@ gm200_disp = {
.intr = gf119_disp_intr, .intr = gf119_disp_intr,
.intr_error = gf119_disp_intr_error, .intr_error = gf119_disp_intr_error,
.uevent = &gf119_disp_chan_uevent, .uevent = &gf119_disp_chan_uevent,
.super = gf119_disp_intr_supervisor, .super = gf119_disp_super,
.root = &gm200_disp_root_oclass, .root = &gm200_disp_root_oclass,
.head.vblank_init = gf119_disp_vblank_init, .head.new = gf119_head_new,
.head.vblank_fini = gf119_disp_vblank_fini, .dac = { .nr = 3, .new = gf119_dac_new },
.head.scanoutpos = gf119_disp_root_scanoutpos, .sor = { .nr = 4, .new = gm200_sor_new },
.outp.internal.crt = nv50_dac_output_new,
.outp.internal.tmds = nv50_sor_output_new,
.outp.internal.lvds = nv50_sor_output_new,
.outp.internal.dp = gm200_sor_dp_new,
.dac.nr = 3,
.dac.power = nv50_dac_power,
.dac.sense = nv50_dac_sense,
.sor.nr = 4,
.sor.power = nv50_sor_power,
.sor.hda_eld = gf119_hda_eld,
.sor.hdmi = gk104_hdmi_ctrl,
.sor.magic = gm200_sor_magic,
}; };
int int
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
* Authors: Ben Skeggs <bskeggs@redhat.com> * Authors: Ben Skeggs <bskeggs@redhat.com>
*/ */
#include "nv50.h" #include "nv50.h"
#include "head.h"
#include "ior.h"
#include "rootnv50.h" #include "rootnv50.h"
static const struct nv50_disp_func static const struct nv50_disp_func
...@@ -29,23 +31,10 @@ gp100_disp = { ...@@ -29,23 +31,10 @@ gp100_disp = {
.intr = gf119_disp_intr, .intr = gf119_disp_intr,
.intr_error = gf119_disp_intr_error, .intr_error = gf119_disp_intr_error,
.uevent = &gf119_disp_chan_uevent, .uevent = &gf119_disp_chan_uevent,
.super = gf119_disp_intr_supervisor, .super = gf119_disp_super,
.root = &gp100_disp_root_oclass, .root = &gp100_disp_root_oclass,
.head.vblank_init = gf119_disp_vblank_init, .head.new = gf119_head_new,
.head.vblank_fini = gf119_disp_vblank_fini, .sor = { .nr = 4, .new = gm200_sor_new },
.head.scanoutpos = gf119_disp_root_scanoutpos,
.outp.internal.crt = nv50_dac_output_new,
.outp.internal.tmds = nv50_sor_output_new,
.outp.internal.lvds = nv50_sor_output_new,
.outp.internal.dp = gm200_sor_dp_new,
.dac.nr = 3,
.dac.power = nv50_dac_power,
.dac.sense = nv50_dac_sense,
.sor.nr = 4,
.sor.power = nv50_sor_power,
.sor.hda_eld = gf119_hda_eld,
.sor.hdmi = gk104_hdmi_ctrl,
.sor.magic = gm200_sor_magic,
}; };
int int
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
* Authors: Ben Skeggs <bskeggs@redhat.com> * Authors: Ben Skeggs <bskeggs@redhat.com>
*/ */
#include "nv50.h" #include "nv50.h"
#include "head.h"
#include "ior.h"
#include "rootnv50.h" #include "rootnv50.h"
static void static void
...@@ -55,23 +57,10 @@ gp102_disp = { ...@@ -55,23 +57,10 @@ gp102_disp = {
.intr = gf119_disp_intr, .intr = gf119_disp_intr,
.intr_error = gp102_disp_intr_error, .intr_error = gp102_disp_intr_error,
.uevent = &gf119_disp_chan_uevent, .uevent = &gf119_disp_chan_uevent,
.super = gf119_disp_intr_supervisor, .super = gf119_disp_super,
.root = &gp102_disp_root_oclass, .root = &gp102_disp_root_oclass,
.head.vblank_init = gf119_disp_vblank_init, .head.new = gf119_head_new,
.head.vblank_fini = gf119_disp_vblank_fini, .sor = { .nr = 4, .new = gm200_sor_new },
.head.scanoutpos = gf119_disp_root_scanoutpos,
.outp.internal.crt = nv50_dac_output_new,
.outp.internal.tmds = nv50_sor_output_new,
.outp.internal.lvds = nv50_sor_output_new,
.outp.internal.dp = gm200_sor_dp_new,
.dac.nr = 3,
.dac.power = nv50_dac_power,
.dac.sense = nv50_dac_sense,
.sor.nr = 4,
.sor.power = nv50_sor_power,
.sor.hda_eld = gf119_hda_eld,
.sor.hdmi = gk104_hdmi_ctrl,
.sor.magic = gm200_sor_magic,
}; };
int int
......
...@@ -22,30 +22,20 @@ ...@@ -22,30 +22,20 @@
* Authors: Ben Skeggs * Authors: Ben Skeggs
*/ */
#include "nv50.h" #include "nv50.h"
#include "head.h"
#include "ior.h"
#include "rootnv50.h" #include "rootnv50.h"
static const struct nv50_disp_func static const struct nv50_disp_func
gt200_disp = { gt200_disp = {
.intr = nv50_disp_intr, .intr = nv50_disp_intr,
.uevent = &nv50_disp_chan_uevent, .uevent = &nv50_disp_chan_uevent,
.super = nv50_disp_intr_supervisor, .super = nv50_disp_super,
.root = &gt200_disp_root_oclass, .root = &gt200_disp_root_oclass,
.head.vblank_init = nv50_disp_vblank_init, .head.new = nv50_head_new,
.head.vblank_fini = nv50_disp_vblank_fini, .dac = { .nr = 3, .new = nv50_dac_new },
.head.scanoutpos = nv50_disp_root_scanoutpos, .sor = { .nr = 2, .new = g84_sor_new },
.outp.internal.crt = nv50_dac_output_new, .pior = { .nr = 3, .new = nv50_pior_new },
.outp.internal.tmds = nv50_sor_output_new,
.outp.internal.lvds = nv50_sor_output_new,
.outp.external.tmds = nv50_pior_output_new,
.outp.external.dp = nv50_pior_dp_new,
.dac.nr = 3,
.dac.power = nv50_dac_power,
.dac.sense = nv50_dac_sense,
.sor.nr = 2,
.sor.power = nv50_sor_power,
.sor.hdmi = g84_hdmi_ctrl,
.pior.nr = 3,
.pior.power = nv50_pior_power,
}; };
int int
......
...@@ -22,32 +22,20 @@ ...@@ -22,32 +22,20 @@
* Authors: Ben Skeggs * Authors: Ben Skeggs
*/ */
#include "nv50.h" #include "nv50.h"
#include "head.h"
#include "ior.h"
#include "rootnv50.h" #include "rootnv50.h"
static const struct nv50_disp_func static const struct nv50_disp_func
gt215_disp = { gt215_disp = {
.intr = nv50_disp_intr, .intr = nv50_disp_intr,
.uevent = &nv50_disp_chan_uevent, .uevent = &nv50_disp_chan_uevent,
.super = nv50_disp_intr_supervisor, .super = nv50_disp_super,
.root = &gt215_disp_root_oclass, .root = &gt215_disp_root_oclass,
.head.vblank_init = nv50_disp_vblank_init, .head.new = nv50_head_new,
.head.vblank_fini = nv50_disp_vblank_fini, .dac = { .nr = 3, .new = nv50_dac_new },
.head.scanoutpos = nv50_disp_root_scanoutpos, .sor = { .nr = 4, .new = gt215_sor_new },
.outp.internal.crt = nv50_dac_output_new, .pior = { .nr = 3, .new = nv50_pior_new },
.outp.internal.tmds = nv50_sor_output_new,
.outp.internal.lvds = nv50_sor_output_new,
.outp.internal.dp = g94_sor_dp_new,
.outp.external.tmds = nv50_pior_output_new,
.outp.external.dp = nv50_pior_dp_new,
.dac.nr = 3,
.dac.power = nv50_dac_power,
.dac.sense = nv50_dac_sense,
.sor.nr = 4,
.sor.power = nv50_sor_power,
.sor.hda_eld = gt215_hda_eld,
.sor.hdmi = gt215_hdmi_ctrl,
.pior.nr = 3,
.pior.power = nv50_pior_power,
}; };
int int
......
...@@ -21,63 +21,34 @@ ...@@ -21,63 +21,34 @@
* *
* Authors: Ben Skeggs * Authors: Ben Skeggs
*/ */
#include "nv50.h" #include "ior.h"
#include "outp.h"
#include <core/client.h> void
#include <subdev/bios.h> gf119_hda_eld(struct nvkm_ior *ior, u8 *data, u8 size)
#include <subdev/bios/dcb.h>
#include <subdev/timer.h>
#include <nvif/cl5070.h>
#include <nvif/unpack.h>
int
gf119_hda_eld(NV50_DISP_MTHD_V1)
{ {
struct nvkm_device *device = disp->base.engine.subdev.device; struct nvkm_device *device = ior->disp->engine.subdev.device;
union { const u32 soff = 0x030 * ior->id;
struct nv50_disp_sor_hda_eld_v0 v0; int i;
} *args = data;
const u32 soff = outp->or * 0x030;
const u32 hoff = head * 0x800;
int ret = -ENOSYS, i;
nvif_ioctl(object, "disp sor hda eld size %d\n", size);
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
nvif_ioctl(object, "disp sor hda eld vers %d\n",
args->v0.version);
if (size > 0x60)
return -E2BIG;
} else
return ret;
if (size && args->v0.data[0]) {
if (outp->info.type == DCB_OUTPUT_DP) {
nvkm_mask(device, 0x616618 + hoff, 0x8000000c, 0x80000001);
nvkm_msec(device, 2000,
u32 tmp = nvkm_rd32(device, 0x616618 + hoff);
if (!(tmp & 0x80000000))
break;
);
}
nvkm_mask(device, 0x616548 + hoff, 0x00000070, 0x00000000);
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
nvkm_wr32(device, 0x10ec00 + soff, (i << 8) | args->v0.data[i]); nvkm_wr32(device, 0x10ec00 + soff, (i << 8) | data[i]);
for (; i < 0x60; i++) for (; i < 0x60; i++)
nvkm_wr32(device, 0x10ec00 + soff, (i << 8)); nvkm_wr32(device, 0x10ec00 + soff, (i << 8));
nvkm_mask(device, 0x10ec10 + soff, 0x80000003, 0x80000003); nvkm_mask(device, 0x10ec10 + soff, 0x80000002, 0x80000002);
}
void
gf119_hda_hpd(struct nvkm_ior *ior, int head, bool present)
{
struct nvkm_device *device = ior->disp->engine.subdev.device;
const u32 hoff = 0x800 * head;
u32 data = 0x80000000;
u32 mask = 0x80000001;
if (present) {
nvkm_mask(device, 0x616548 + hoff, 0x00000070, 0x00000000);
data |= 0x00000001;
} else { } else {
if (outp->info.type == DCB_OUTPUT_DP) { mask |= 0x00000002;
nvkm_mask(device, 0x616618 + hoff, 0x80000001, 0x80000000);
nvkm_msec(device, 2000,
u32 tmp = nvkm_rd32(device, 0x616618 + hoff);
if (!(tmp & 0x80000000))
break;
);
} }
nvkm_mask(device, 0x10ec10 + soff, 0x80000003, 0x80000000 | !!size); nvkm_mask(device, 0x10ec10 + ior->id * 0x030, mask, data);
}
return 0;
} }
...@@ -21,59 +21,31 @@ ...@@ -21,59 +21,31 @@
* *
* Authors: Ben Skeggs * Authors: Ben Skeggs
*/ */
#include "nv50.h" #include "ior.h"
#include "outp.h"
#include <core/client.h> void
#include <subdev/timer.h> gt215_hda_eld(struct nvkm_ior *ior, u8 *data, u8 size)
#include <nvif/cl5070.h>
#include <nvif/unpack.h>
int
gt215_hda_eld(NV50_DISP_MTHD_V1)
{ {
struct nvkm_device *device = disp->base.engine.subdev.device; struct nvkm_device *device = ior->disp->engine.subdev.device;
union { const u32 soff = ior->id * 0x800;
struct nv50_disp_sor_hda_eld_v0 v0; int i;
} *args = data;
const u32 soff = outp->or * 0x800;
int ret = -ENOSYS, i;
nvif_ioctl(object, "disp sor hda eld size %d\n", size);
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
nvif_ioctl(object, "disp sor hda eld vers %d\n",
args->v0.version);
if (size > 0x60)
return -E2BIG;
} else
return ret;
if (size && args->v0.data[0]) {
if (outp->info.type == DCB_OUTPUT_DP) {
nvkm_mask(device, 0x61c1e0 + soff, 0x8000000d, 0x80000001);
nvkm_msec(device, 2000,
u32 tmp = nvkm_rd32(device, 0x61c1e0 + soff);
if (!(tmp & 0x80000000))
break;
);
}
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
nvkm_wr32(device, 0x61c440 + soff, (i << 8) | args->v0.data[i]); nvkm_wr32(device, 0x61c440 + soff, (i << 8) | data[i]);
for (; i < 0x60; i++) for (; i < 0x60; i++)
nvkm_wr32(device, 0x61c440 + soff, (i << 8)); nvkm_wr32(device, 0x61c440 + soff, (i << 8));
nvkm_mask(device, 0x61c448 + soff, 0x80000003, 0x80000003); nvkm_mask(device, 0x61c448 + soff, 0x80000002, 0x80000002);
} else { }
if (outp->info.type == DCB_OUTPUT_DP) {
nvkm_mask(device, 0x61c1e0 + soff, 0x80000001, 0x80000000);
nvkm_msec(device, 2000,
u32 tmp = nvkm_rd32(device, 0x61c1e0 + soff);
if (!(tmp & 0x80000000))
break;
);
}
nvkm_mask(device, 0x61c448 + soff, 0x80000003, 0x80000000 | !!size);
}
return 0; void
gt215_hda_hpd(struct nvkm_ior *ior, int head, bool present)
{
struct nvkm_device *device = ior->disp->engine.subdev.device;
u32 data = 0x80000000;
u32 mask = 0x80000001;
if (present)
data |= 0x00000001;
else
mask |= 0x00000002;
nvkm_mask(device, 0x61c448 + ior->id * 0x800, mask, data);
} }
#include "hdmi.h"
void pack_hdmi_infoframe(struct packed_hdmi_infoframe *packed_frame,
u8 *raw_frame, ssize_t len)
{
u32 header = 0;
u32 subpack0_low = 0;
u32 subpack0_high = 0;
u32 subpack1_low = 0;
u32 subpack1_high = 0;
switch (len) {
/*
* "When in doubt, use brute force."
* -- Ken Thompson.
*/
default:
/*
* We presume that no valid frame is longer than 17
* octets, including header... And truncate to that
* if it's longer.
*/
case 17:
subpack1_high = (raw_frame[16] << 16);
case 16:
subpack1_high |= (raw_frame[15] << 8);
case 15:
subpack1_high |= raw_frame[14];
case 14:
subpack1_low = (raw_frame[13] << 24);
case 13:
subpack1_low |= (raw_frame[12] << 16);
case 12:
subpack1_low |= (raw_frame[11] << 8);
case 11:
subpack1_low |= raw_frame[10];
case 10:
subpack0_high = (raw_frame[9] << 16);
case 9:
subpack0_high |= (raw_frame[8] << 8);
case 8:
subpack0_high |= raw_frame[7];
case 7:
subpack0_low = (raw_frame[6] << 24);
case 6:
subpack0_low |= (raw_frame[5] << 16);
case 5:
subpack0_low |= (raw_frame[4] << 8);
case 4:
subpack0_low |= raw_frame[3];
case 3:
header = (raw_frame[2] << 16);
case 2:
header |= (raw_frame[1] << 8);
case 1:
header |= raw_frame[0];
case 0:
break;
}
packed_frame->header = header;
packed_frame->subpack0_low = subpack0_low;
packed_frame->subpack0_high = subpack0_high;
packed_frame->subpack1_low = subpack1_low;
packed_frame->subpack1_high = subpack1_high;
}
#ifndef __NVKM_DISP_HDMI_H__
#define __NVKM_DISP_HDMI_H__
#include "ior.h"
struct packed_hdmi_infoframe {
u32 header;
u32 subpack0_low;
u32 subpack0_high;
u32 subpack1_low;
u32 subpack1_high;
};
void pack_hdmi_infoframe(struct packed_hdmi_infoframe *packed_frame,
u8 *raw_frame, ssize_t len);
#endif
...@@ -21,54 +21,42 @@ ...@@ -21,54 +21,42 @@
* *
* Authors: Ben Skeggs * Authors: Ben Skeggs
*/ */
#include "nv50.h" #include "hdmi.h"
#include <core/client.h> void
g84_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet,
#include <nvif/cl5070.h> u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size)
#include <nvif/unpack.h>
int
g84_hdmi_ctrl(NV50_DISP_MTHD_V1)
{ {
struct nvkm_device *device = disp->base.engine.subdev.device; struct nvkm_device *device = ior->disp->engine.subdev.device;
const u32 hoff = (head * 0x800); const u32 ctrl = 0x40000000 * enable |
union { 0x1f000000 /* ??? */ |
struct nv50_disp_sor_hdmi_pwr_v0 v0; max_ac_packet << 16 |
} *args = data; rekey;
u32 ctrl; const u32 hoff = head * 0x800;
int ret = -ENOSYS; struct packed_hdmi_infoframe avi_infoframe;
struct packed_hdmi_infoframe vendor_infoframe;
nvif_ioctl(object, "disp sor hdmi ctrl size %d\n", size); pack_hdmi_infoframe(&avi_infoframe, avi, avi_size);
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size);
nvif_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
"max_ac_packet %d rekey %d\n",
args->v0.version, args->v0.state,
args->v0.max_ac_packet, args->v0.rekey);
if (args->v0.max_ac_packet > 0x1f || args->v0.rekey > 0x7f)
return -EINVAL;
ctrl = 0x40000000 * !!args->v0.state;
ctrl |= args->v0.max_ac_packet << 16;
ctrl |= args->v0.rekey;
ctrl |= 0x1f000000; /* ??? */
} else
return ret;
if (!(ctrl & 0x40000000)) { if (!(ctrl & 0x40000000)) {
nvkm_mask(device, 0x6165a4 + hoff, 0x40000000, 0x00000000); nvkm_mask(device, 0x6165a4 + hoff, 0x40000000, 0x00000000);
nvkm_mask(device, 0x61653c + hoff, 0x00000001, 0x00000000);
nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000000); nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000000);
nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000000); nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000000);
return 0; return;
} }
/* AVI InfoFrame */ /* AVI InfoFrame */
nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000000); nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000000);
nvkm_wr32(device, 0x616528 + hoff, 0x000d0282); if (avi_size) {
nvkm_wr32(device, 0x61652c + hoff, 0x0000006f); nvkm_wr32(device, 0x616528 + hoff, avi_infoframe.header);
nvkm_wr32(device, 0x616530 + hoff, 0x00000000); nvkm_wr32(device, 0x61652c + hoff, avi_infoframe.subpack0_low);
nvkm_wr32(device, 0x616534 + hoff, 0x00000000); nvkm_wr32(device, 0x616530 + hoff, avi_infoframe.subpack0_high);
nvkm_wr32(device, 0x616538 + hoff, 0x00000000); nvkm_wr32(device, 0x616534 + hoff, avi_infoframe.subpack1_low);
nvkm_wr32(device, 0x616538 + hoff, avi_infoframe.subpack1_high);
nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000001); nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000001);
}
/* Audio InfoFrame */ /* Audio InfoFrame */
nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000000); nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000000);
...@@ -77,6 +65,18 @@ g84_hdmi_ctrl(NV50_DISP_MTHD_V1) ...@@ -77,6 +65,18 @@ g84_hdmi_ctrl(NV50_DISP_MTHD_V1)
nvkm_wr32(device, 0x616510 + hoff, 0x00000000); nvkm_wr32(device, 0x616510 + hoff, 0x00000000);
nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000001); nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000001);
/* Vendor InfoFrame */
nvkm_mask(device, 0x61653c + hoff, 0x00010001, 0x00010000);
if (vendor_size) {
nvkm_wr32(device, 0x616544 + hoff, vendor_infoframe.header);
nvkm_wr32(device, 0x616548 + hoff, vendor_infoframe.subpack0_low);
nvkm_wr32(device, 0x61654c + hoff, vendor_infoframe.subpack0_high);
/* Is there a second (or up to fourth?) set of subpack registers here? */
/* nvkm_wr32(device, 0x616550 + hoff, vendor_infoframe->subpack1_low); */
/* nvkm_wr32(device, 0x616554 + hoff, vendor_infoframe->subpack1_high); */
nvkm_mask(device, 0x61653c + hoff, 0x00010001, 0x00010001);
}
nvkm_mask(device, 0x6165d0 + hoff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */ nvkm_mask(device, 0x6165d0 + hoff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */
nvkm_mask(device, 0x616568 + hoff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */ nvkm_mask(device, 0x616568 + hoff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */
nvkm_mask(device, 0x616578 + hoff, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */ nvkm_mask(device, 0x616578 + hoff, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */
...@@ -88,5 +88,4 @@ g84_hdmi_ctrl(NV50_DISP_MTHD_V1) ...@@ -88,5 +88,4 @@ g84_hdmi_ctrl(NV50_DISP_MTHD_V1)
/* HDMI_CTRL */ /* HDMI_CTRL */
nvkm_mask(device, 0x6165a4 + hoff, 0x5f1f007f, ctrl); nvkm_mask(device, 0x6165a4 + hoff, 0x5f1f007f, ctrl);
return 0;
} }
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
* Authors: Ben Skeggs * Authors: Ben Skeggs
*/ */
#include "channv50.h" #include "channv50.h"
#include "head.h"
#include "rootnv50.h" #include "rootnv50.h"
#include <core/client.h> #include <core/client.h>
...@@ -48,7 +49,7 @@ nv50_disp_oimm_new(const struct nv50_disp_chan_func *func, ...@@ -48,7 +49,7 @@ nv50_disp_oimm_new(const struct nv50_disp_chan_func *func,
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
nvif_ioctl(parent, "create disp overlay vers %d head %d\n", nvif_ioctl(parent, "create disp overlay vers %d head %d\n",
args->v0.version, args->v0.head); args->v0.version, args->v0.head);
if (args->v0.head > disp->base.head.nr) if (!nvkm_head_find(&disp->base, args->v0.head))
return -EINVAL; return -EINVAL;
head = args->v0.head; head = args->v0.head;
} else } else
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment