Skip to content

Commit

Permalink
drm/nouveau: introduce gpio engine
Browse files Browse the repository at this point in the history
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
  • Loading branch information
Ben Skeggs committed Jul 26, 2010
1 parent bf563a6 commit ee2e013
Show file tree
Hide file tree
Showing 11 changed files with 100 additions and 38 deletions.
2 changes: 1 addition & 1 deletion drivers/gpu/drm/nouveau/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
nv50_cursor.o nv50_display.o nv50_fbcon.o \
nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \
nv04_crtc.o nv04_display.o nv04_cursor.o nv04_fbcon.o \
nv17_gpio.o nv50_gpio.o \
nv10_gpio.o nv50_gpio.o \
nv50_calc.o

nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o
Expand Down
3 changes: 2 additions & 1 deletion drivers/gpu/drm/nouveau/nouveau_bios.c
Original file line number Diff line number Diff line change
Expand Up @@ -3136,6 +3136,7 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
*/

struct drm_nouveau_private *dev_priv = bios->dev->dev_private;
struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c };
int i;

Expand All @@ -3156,7 +3157,7 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
BIOSLOG(bios, "0x%04X: set gpio 0x%02x, state %d\n",
offset, gpio->tag, gpio->state_default);
if (bios->execute)
nv50_gpio_set(bios->dev, gpio->tag, gpio->state_default);
pgpio->set(bios->dev, gpio->tag, gpio->state_default);

/* The NVIDIA binary driver doesn't appear to actually do
* any of this, my VBIOS does however.
Expand Down
6 changes: 4 additions & 2 deletions drivers/gpu/drm/nouveau/nouveau_dp.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,8 @@ bool
nouveau_dp_link_train(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nouveau_connector *nv_connector;
struct bit_displayport_encoder_table *dpe;
Expand All @@ -295,7 +297,7 @@ nouveau_dp_link_train(struct drm_encoder *encoder)
/* disable hotplug detect, this flips around on some panels during
* link training.
*/
nv50_gpio_irq_enable(dev, nv_connector->dcb->gpio_tag, false);
pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false);

if (dpe->script0) {
NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or);
Expand Down Expand Up @@ -436,7 +438,7 @@ nouveau_dp_link_train(struct drm_encoder *encoder)
}

/* re-enable hotplug detect */
nv50_gpio_irq_enable(dev, nv_connector->dcb->gpio_tag, true);
pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, true);

return eq_done;
}
Expand Down
18 changes: 15 additions & 3 deletions drivers/gpu/drm/nouveau/nouveau_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,16 @@ struct nouveau_display_engine {
void (*destroy)(struct drm_device *);
};

struct nouveau_gpio_engine {
int (*init)(struct drm_device *);
void (*takedown)(struct drm_device *);

int (*get)(struct drm_device *, enum dcb_gpio_tag);
int (*set)(struct drm_device *, enum dcb_gpio_tag, int state);

void (*irq_enable)(struct drm_device *, enum dcb_gpio_tag, bool on);
};

struct nouveau_engine {
struct nouveau_instmem_engine instmem;
struct nouveau_mc_engine mc;
Expand All @@ -367,6 +377,7 @@ struct nouveau_engine {
struct nouveau_pgraph_engine graph;
struct nouveau_fifo_engine fifo;
struct nouveau_display_engine display;
struct nouveau_gpio_engine gpio;
};

struct nouveau_pll_vals {
Expand Down Expand Up @@ -1149,11 +1160,12 @@ extern int nouveau_gem_ioctl_cpu_fini(struct drm_device *, void *,
extern int nouveau_gem_ioctl_info(struct drm_device *, void *,
struct drm_file *);

/* nv17_gpio.c */
int nv17_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);
int nv17_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state);
/* nv10_gpio.c */
int nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);
int nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state);

/* nv50_gpio.c */
int nv50_gpio_init(struct drm_device *dev);
int nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);
int nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state);
void nv50_gpio_irq_enable(struct drm_device *, enum dcb_gpio_tag, bool on);
Expand Down
41 changes: 40 additions & 1 deletion drivers/gpu/drm/nouveau/nouveau_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "nv50_display.h"

static void nouveau_stub_takedown(struct drm_device *dev) {}
static int nouveau_stub_init(struct drm_device *dev) { return 0; }

static int nouveau_init_engine_ptrs(struct drm_device *dev)
{
Expand Down Expand Up @@ -89,6 +90,11 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->display.create = nv04_display_create;
engine->display.init = nv04_display_init;
engine->display.destroy = nv04_display_destroy;
engine->gpio.init = nouveau_stub_init;
engine->gpio.takedown = nouveau_stub_takedown;
engine->gpio.get = NULL;
engine->gpio.set = NULL;
engine->gpio.irq_enable = NULL;
break;
case 0x10:
engine->instmem.init = nv04_instmem_init;
Expand Down Expand Up @@ -136,6 +142,11 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->display.create = nv04_display_create;
engine->display.init = nv04_display_init;
engine->display.destroy = nv04_display_destroy;
engine->gpio.init = nouveau_stub_init;
engine->gpio.takedown = nouveau_stub_takedown;
engine->gpio.get = nv10_gpio_get;
engine->gpio.set = nv10_gpio_set;
engine->gpio.irq_enable = NULL;
break;
case 0x20:
engine->instmem.init = nv04_instmem_init;
Expand Down Expand Up @@ -183,6 +194,11 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->display.create = nv04_display_create;
engine->display.init = nv04_display_init;
engine->display.destroy = nv04_display_destroy;
engine->gpio.init = nouveau_stub_init;
engine->gpio.takedown = nouveau_stub_takedown;
engine->gpio.get = nv10_gpio_get;
engine->gpio.set = nv10_gpio_set;
engine->gpio.irq_enable = NULL;
break;
case 0x30:
engine->instmem.init = nv04_instmem_init;
Expand Down Expand Up @@ -230,6 +246,11 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->display.create = nv04_display_create;
engine->display.init = nv04_display_init;
engine->display.destroy = nv04_display_destroy;
engine->gpio.init = nouveau_stub_init;
engine->gpio.takedown = nouveau_stub_takedown;
engine->gpio.get = nv10_gpio_get;
engine->gpio.set = nv10_gpio_set;
engine->gpio.irq_enable = NULL;
break;
case 0x40:
case 0x60:
Expand Down Expand Up @@ -278,6 +299,11 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->display.create = nv04_display_create;
engine->display.init = nv04_display_init;
engine->display.destroy = nv04_display_destroy;
engine->gpio.init = nouveau_stub_init;
engine->gpio.takedown = nouveau_stub_takedown;
engine->gpio.get = nv10_gpio_get;
engine->gpio.set = nv10_gpio_set;
engine->gpio.irq_enable = NULL;
break;
case 0x50:
case 0x80: /* gotta love NVIDIA's consistency.. */
Expand Down Expand Up @@ -327,6 +353,11 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->display.create = nv50_display_create;
engine->display.init = nv50_display_init;
engine->display.destroy = nv50_display_destroy;
engine->gpio.init = nv50_gpio_init;
engine->gpio.takedown = nouveau_stub_takedown;
engine->gpio.get = nv50_gpio_get;
engine->gpio.set = nv50_gpio_set;
engine->gpio.irq_enable = nv50_gpio_irq_enable;
break;
default:
NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset);
Expand Down Expand Up @@ -485,10 +516,15 @@ nouveau_card_init(struct drm_device *dev)
if (ret)
goto out_gpuobj;

/* PGPIO */
ret = engine->gpio.init(dev);
if (ret)
goto out_mc;

/* PTIMER */
ret = engine->timer.init(dev);
if (ret)
goto out_mc;
goto out_gpio;

/* PFB */
ret = engine->fb.init(dev);
Expand Down Expand Up @@ -554,6 +590,8 @@ nouveau_card_init(struct drm_device *dev)
engine->fb.takedown(dev);
out_timer:
engine->timer.takedown(dev);
out_gpio:
engine->gpio.takedown(dev);
out_mc:
engine->mc.takedown(dev);
out_gpuobj:
Expand Down Expand Up @@ -592,6 +630,7 @@ static void nouveau_card_takedown(struct drm_device *dev)
}
engine->fb.takedown(dev);
engine->timer.takedown(dev);
engine->gpio.takedown(dev);
engine->mc.takedown(dev);
engine->display.late_takedown(dev);

Expand Down
13 changes: 7 additions & 6 deletions drivers/gpu/drm/nouveau/nv04_dac.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio;
struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
uint32_t sample, testval, regoffset = nv04_dac_output_offset(encoder);
uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput,
Expand Down Expand Up @@ -251,11 +252,11 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder)
nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf);
}

saved_gpio1 = nv17_gpio_get(dev, DCB_GPIO_TVDAC1);
saved_gpio0 = nv17_gpio_get(dev, DCB_GPIO_TVDAC0);
saved_gpio1 = gpio->get(dev, DCB_GPIO_TVDAC1);
saved_gpio0 = gpio->get(dev, DCB_GPIO_TVDAC0);

nv17_gpio_set(dev, DCB_GPIO_TVDAC1, dcb->type == OUTPUT_TV);
nv17_gpio_set(dev, DCB_GPIO_TVDAC0, dcb->type == OUTPUT_TV);
gpio->set(dev, DCB_GPIO_TVDAC1, dcb->type == OUTPUT_TV);
gpio->set(dev, DCB_GPIO_TVDAC0, dcb->type == OUTPUT_TV);

msleep(4);

Expand Down Expand Up @@ -303,8 +304,8 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder)
nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4);
nvWriteMC(dev, NV_PBUS_POWERCTRL_2, saved_powerctrl_2);

nv17_gpio_set(dev, DCB_GPIO_TVDAC1, saved_gpio1);
nv17_gpio_set(dev, DCB_GPIO_TVDAC0, saved_gpio0);
gpio->set(dev, DCB_GPIO_TVDAC1, saved_gpio1);
gpio->set(dev, DCB_GPIO_TVDAC0, saved_gpio0);

return sample;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ get_gpio_location(struct dcb_gpio_entry *ent, uint32_t *reg, uint32_t *shift,
}

int
nv17_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag)
nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag)
{
struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag);
uint32_t reg, shift, mask, value;
Expand All @@ -72,7 +72,7 @@ nv17_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag)
}

int
nv17_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state)
nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state)
{
struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag);
uint32_t reg, shift, mask, value;
Expand Down
19 changes: 11 additions & 8 deletions drivers/gpu/drm/nouveau/nv17_tv.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio;
uint32_t testval, regoffset = nv04_dac_output_offset(encoder);
uint32_t gpio0, gpio1, fp_htotal, fp_hsync_start, fp_hsync_end,
fp_control, test_ctrl, dacclk, ctv_14, ctv_1c, ctv_6c;
Expand All @@ -52,8 +53,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder)
head = (dacclk & 0x100) >> 8;

/* Save the previous state. */
gpio1 = nv17_gpio_get(dev, DCB_GPIO_TVDAC1);
gpio0 = nv17_gpio_get(dev, DCB_GPIO_TVDAC0);
gpio1 = gpio->get(dev, DCB_GPIO_TVDAC1);
gpio0 = gpio->get(dev, DCB_GPIO_TVDAC0);
fp_htotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL);
fp_hsync_start = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START);
fp_hsync_end = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END);
Expand All @@ -64,8 +65,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder)
ctv_6c = NVReadRAMDAC(dev, head, 0x680c6c);

/* Prepare the DAC for load detection. */
nv17_gpio_set(dev, DCB_GPIO_TVDAC1, true);
nv17_gpio_set(dev, DCB_GPIO_TVDAC0, true);
gpio->set(dev, DCB_GPIO_TVDAC1, true);
gpio->set(dev, DCB_GPIO_TVDAC0, true);

NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, 1343);
NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, 1047);
Expand Down Expand Up @@ -110,8 +111,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder)
NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, fp_hsync_end);
NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, fp_hsync_start);
NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, fp_htotal);
nv17_gpio_set(dev, DCB_GPIO_TVDAC1, gpio1);
nv17_gpio_set(dev, DCB_GPIO_TVDAC0, gpio0);
gpio->set(dev, DCB_GPIO_TVDAC1, gpio1);
gpio->set(dev, DCB_GPIO_TVDAC0, gpio0);

return sample;
}
Expand Down Expand Up @@ -335,6 +336,8 @@ static bool nv17_tv_mode_fixup(struct drm_encoder *encoder,
static void nv17_tv_dpms(struct drm_encoder *encoder, int mode)
{
struct drm_device *dev = encoder->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio;
struct nv17_tv_state *regs = &to_tv_enc(encoder)->state;
struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);

Expand All @@ -359,8 +362,8 @@ static void nv17_tv_dpms(struct drm_encoder *encoder, int mode)

nv_load_ptv(dev, regs, 200);

nv17_gpio_set(dev, DCB_GPIO_TVDAC1, mode == DRM_MODE_DPMS_ON);
nv17_gpio_set(dev, DCB_GPIO_TVDAC0, mode == DRM_MODE_DPMS_ON);
gpio->set(dev, DCB_GPIO_TVDAC1, mode == DRM_MODE_DPMS_ON);
gpio->set(dev, DCB_GPIO_TVDAC0, mode == DRM_MODE_DPMS_ON);

nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON);
}
Expand Down
3 changes: 2 additions & 1 deletion drivers/gpu/drm/nouveau/nv50_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ nv50_display_init(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
struct nouveau_channel *evo = dev_priv->evo;
struct drm_connector *connector;
uint32_t val, ram_amount;
Expand Down Expand Up @@ -379,7 +380,7 @@ nv50_display_init(struct drm_device *dev)
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct nouveau_connector *conn = nouveau_connector(connector);

nv50_gpio_irq_enable(dev, conn->dcb->gpio_tag, true);
pgpio->irq_enable(dev, conn->dcb->gpio_tag, true);
}

return 0;
Expand Down
16 changes: 16 additions & 0 deletions drivers/gpu/drm/nouveau/nv50_gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,19 @@ nv50_gpio_irq_enable(struct drm_device *dev, enum dcb_gpio_tag tag, bool on)
nv_wr32(dev, reg + 4, mask);
nv_mask(dev, reg + 0, mask, on ? mask : 0);
}

int
nv50_gpio_init(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;

/* disable, and ack any pending gpio interrupts */
nv_wr32(dev, 0xe050, 0x00000000);
nv_wr32(dev, 0xe054, 0xffffffff);
if (dev_priv->chipset >= 0x90) {
nv_wr32(dev, 0xe070, 0x00000000);
nv_wr32(dev, 0xe074, 0xffffffff);
}

return 0;
}
13 changes: 0 additions & 13 deletions drivers/gpu/drm/nouveau/nv50_mc.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,7 @@
int
nv50_mc_init(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;

nv_wr32(dev, NV03_PMC_ENABLE, 0xFFFFFFFF);

/* disable, and ack any pending gpio interrupts
* XXX doesn't technically belong here, but it'll do for the moment
*/
nv_wr32(dev, 0xe050, 0x00000000);
nv_wr32(dev, 0xe054, 0xffffffff);
if (dev_priv->chipset >= 0x90) {
nv_wr32(dev, 0xe070, 0x00000000);
nv_wr32(dev, 0xe074, 0xffffffff);
}

return 0;
}

Expand Down

0 comments on commit ee2e013

Please sign in to comment.