Merge branch 'server-fixes' into drm-next
Merge the fixes for the server driver dirty update paths
* server-fixes:
drm/cirrus: deal with bo reserve fail in dirty update path
drm/ast: deal with bo reserve fail in dirty update path
drm/mgag200: deal with bo reserve fail in dirty update path
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile
index 52930a2..998e8b4 100644
--- a/drivers/gpu/drm/nouveau/Makefile
+++ b/drivers/gpu/drm/nouveau/Makefile
@@ -160,6 +160,7 @@
nouveau-y += core/engine/disp/nva3.o
nouveau-y += core/engine/disp/nvd0.o
nouveau-y += core/engine/disp/nve0.o
+nouveau-y += core/engine/disp/nvf0.o
nouveau-y += core/engine/disp/dacnv50.o
nouveau-y += core/engine/disp/dport.o
nouveau-y += core/engine/disp/hdanva3.o
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/base.c b/drivers/gpu/drm/nouveau/core/engine/device/base.c
index 86d2490..4c72571 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/base.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/base.c
@@ -172,7 +172,8 @@
case 0xa0: device->card_type = NV_50; break;
case 0xc0: device->card_type = NV_C0; break;
case 0xd0: device->card_type = NV_D0; break;
- case 0xe0: device->card_type = NV_E0; break;
+ case 0xe0:
+ case 0xf0: device->card_type = NV_E0; break;
default:
break;
}
diff --git a/drivers/gpu/drm/nouveau/core/engine/device/nve0.c b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c
index e6a7794..a354e40 100644
--- a/drivers/gpu/drm/nouveau/core/engine/device/nve0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/device/nve0.c
@@ -141,6 +141,40 @@
device->oclass[NVDEV_ENGINE_VP ] = &nve0_vp_oclass;
device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
break;
+ case 0xf0:
+ device->cname = "GK110";
+ device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass;
+ device->oclass[NVDEV_SUBDEV_GPIO ] = &nve0_gpio_oclass;
+ device->oclass[NVDEV_SUBDEV_I2C ] = &nvd0_i2c_oclass;
+ device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass;
+ device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass;
+ device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
+ device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass;
+ device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass;
+ device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass;
+ device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
+ device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass;
+ device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass;
+ device->oclass[NVDEV_SUBDEV_IBUS ] = &nve0_ibus_oclass;
+ device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+ device->oclass[NVDEV_SUBDEV_VM ] = &nvc0_vmmgr_oclass;
+ device->oclass[NVDEV_SUBDEV_BAR ] = &nvc0_bar_oclass;
+ device->oclass[NVDEV_ENGINE_DMAOBJ ] = &nvd0_dmaeng_oclass;
+#if 0
+ device->oclass[NVDEV_ENGINE_FIFO ] = &nve0_fifo_oclass;
+ device->oclass[NVDEV_ENGINE_SW ] = &nvc0_software_oclass;
+ device->oclass[NVDEV_ENGINE_GR ] = &nve0_graph_oclass;
+#endif
+ device->oclass[NVDEV_ENGINE_DISP ] = &nvf0_disp_oclass;
+#if 0
+ device->oclass[NVDEV_ENGINE_COPY0 ] = &nve0_copy0_oclass;
+ device->oclass[NVDEV_ENGINE_COPY1 ] = &nve0_copy1_oclass;
+ device->oclass[NVDEV_ENGINE_COPY2 ] = &nve0_copy2_oclass;
+ device->oclass[NVDEV_ENGINE_BSP ] = &nve0_bsp_oclass;
+ device->oclass[NVDEV_ENGINE_VP ] = &nve0_vp_oclass;
+ device->oclass[NVDEV_ENGINE_PPP ] = &nvc0_ppp_oclass;
+#endif
+ break;
default:
nv_fatal(device, "unknown Kepler chipset\n");
return -EINVAL;
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c b/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
new file mode 100644
index 0000000..a488c36
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2012 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <engine/software.h>
+#include <engine/disp.h>
+
+#include <core/class.h>
+
+#include "nv50.h"
+
+static struct nouveau_oclass
+nvf0_disp_sclass[] = {
+ { NVF0_DISP_MAST_CLASS, &nvd0_disp_mast_ofuncs },
+ { NVF0_DISP_SYNC_CLASS, &nvd0_disp_sync_ofuncs },
+ { NVF0_DISP_OVLY_CLASS, &nvd0_disp_ovly_ofuncs },
+ { NVF0_DISP_OIMM_CLASS, &nvd0_disp_oimm_ofuncs },
+ { NVF0_DISP_CURS_CLASS, &nvd0_disp_curs_ofuncs },
+ {}
+};
+
+static struct nouveau_oclass
+nvf0_disp_base_oclass[] = {
+ { NVF0_DISP_CLASS, &nvd0_disp_base_ofuncs, nva3_disp_base_omthds },
+ {}
+};
+
+static int
+nvf0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+ struct nouveau_oclass *oclass, void *data, u32 size,
+ struct nouveau_object **pobject)
+{
+ struct nv50_disp_priv *priv;
+ int heads = nv_rd32(parent, 0x022448);
+ int ret;
+
+ ret = nouveau_disp_create(parent, engine, oclass, heads,
+ "PDISP", "display", &priv);
+ *pobject = nv_object(priv);
+ if (ret)
+ return ret;
+
+ nv_engine(priv)->sclass = nvf0_disp_base_oclass;
+ nv_engine(priv)->cclass = &nv50_disp_cclass;
+ nv_subdev(priv)->intr = nvd0_disp_intr;
+ INIT_WORK(&priv->supervisor, nvd0_disp_intr_supervisor);
+ priv->sclass = nvf0_disp_sclass;
+ priv->head.nr = heads;
+ priv->dac.nr = 3;
+ priv->sor.nr = 4;
+ priv->dac.power = nv50_dac_power;
+ priv->dac.sense = nv50_dac_sense;
+ priv->sor.power = nv50_sor_power;
+ priv->sor.hda_eld = nvd0_hda_eld;
+ priv->sor.hdmi = nvd0_hdmi_ctrl;
+ priv->sor.dp = &nvd0_sor_dp_func;
+ return 0;
+}
+
+struct nouveau_oclass
+nvf0_disp_oclass = {
+ .handle = NV_ENGINE(DISP, 0x92),
+ .ofuncs = &(struct nouveau_ofuncs) {
+ .ctor = nvf0_disp_ctor,
+ .dtor = _nouveau_disp_dtor,
+ .init = _nouveau_disp_init,
+ .fini = _nouveau_disp_fini,
+ },
+};
diff --git a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c
index d152875..944e73a 100644
--- a/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/dmaobj/nvd0.c
@@ -50,6 +50,9 @@
case NVE0_DISP_MAST_CLASS:
case NVE0_DISP_SYNC_CLASS:
case NVE0_DISP_OVLY_CLASS:
+ case NVF0_DISP_MAST_CLASS:
+ case NVF0_DISP_SYNC_CLASS:
+ case NVF0_DISP_OVLY_CLASS:
break;
default:
return -EINVAL;
diff --git a/drivers/gpu/drm/nouveau/core/include/core/class.h b/drivers/gpu/drm/nouveau/core/include/core/class.h
index 92d3ab1..0a393f7 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/class.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/class.h
@@ -169,6 +169,7 @@
* 8570: NVA3_DISP
* 9070: NVD0_DISP
* 9170: NVE0_DISP
+ * 9270: NVF0_DISP
*/
#define NV50_DISP_CLASS 0x00005070
@@ -178,6 +179,7 @@
#define NVA3_DISP_CLASS 0x00008570
#define NVD0_DISP_CLASS 0x00009070
#define NVE0_DISP_CLASS 0x00009170
+#define NVF0_DISP_CLASS 0x00009270
#define NV50_DISP_SOR_MTHD 0x00010000
#define NV50_DISP_SOR_MTHD_TYPE 0x0000f000
@@ -246,6 +248,7 @@
* 857a: NVA3_DISP_CURS
* 907a: NVD0_DISP_CURS
* 917a: NVE0_DISP_CURS
+ * 927a: NVF0_DISP_CURS
*/
#define NV50_DISP_CURS_CLASS 0x0000507a
@@ -255,6 +258,7 @@
#define NVA3_DISP_CURS_CLASS 0x0000857a
#define NVD0_DISP_CURS_CLASS 0x0000907a
#define NVE0_DISP_CURS_CLASS 0x0000917a
+#define NVF0_DISP_CURS_CLASS 0x0000927a
struct nv50_display_curs_class {
u32 head;
@@ -267,6 +271,7 @@
* 857b: NVA3_DISP_OIMM
* 907b: NVD0_DISP_OIMM
* 917b: NVE0_DISP_OIMM
+ * 927b: NVE0_DISP_OIMM
*/
#define NV50_DISP_OIMM_CLASS 0x0000507b
@@ -276,6 +281,7 @@
#define NVA3_DISP_OIMM_CLASS 0x0000857b
#define NVD0_DISP_OIMM_CLASS 0x0000907b
#define NVE0_DISP_OIMM_CLASS 0x0000917b
+#define NVF0_DISP_OIMM_CLASS 0x0000927b
struct nv50_display_oimm_class {
u32 head;
@@ -288,6 +294,7 @@
* 857c: NVA3_DISP_SYNC
* 907c: NVD0_DISP_SYNC
* 917c: NVE0_DISP_SYNC
+ * 927c: NVF0_DISP_SYNC
*/
#define NV50_DISP_SYNC_CLASS 0x0000507c
@@ -297,6 +304,7 @@
#define NVA3_DISP_SYNC_CLASS 0x0000857c
#define NVD0_DISP_SYNC_CLASS 0x0000907c
#define NVE0_DISP_SYNC_CLASS 0x0000917c
+#define NVF0_DISP_SYNC_CLASS 0x0000927c
struct nv50_display_sync_class {
u32 pushbuf;
@@ -310,6 +318,7 @@
* 857d: NVA3_DISP_MAST
* 907d: NVD0_DISP_MAST
* 917d: NVE0_DISP_MAST
+ * 927d: NVF0_DISP_MAST
*/
#define NV50_DISP_MAST_CLASS 0x0000507d
@@ -319,6 +328,7 @@
#define NVA3_DISP_MAST_CLASS 0x0000857d
#define NVD0_DISP_MAST_CLASS 0x0000907d
#define NVE0_DISP_MAST_CLASS 0x0000917d
+#define NVF0_DISP_MAST_CLASS 0x0000927d
struct nv50_display_mast_class {
u32 pushbuf;
@@ -331,6 +341,7 @@
* 857e: NVA3_DISP_OVLY
* 907e: NVD0_DISP_OVLY
* 917e: NVE0_DISP_OVLY
+ * 927e: NVF0_DISP_OVLY
*/
#define NV50_DISP_OVLY_CLASS 0x0000507e
@@ -340,6 +351,7 @@
#define NVA3_DISP_OVLY_CLASS 0x0000857e
#define NVD0_DISP_OVLY_CLASS 0x0000907e
#define NVE0_DISP_OVLY_CLASS 0x0000917e
+#define NVF0_DISP_OVLY_CLASS 0x0000927e
struct nv50_display_ovly_class {
u32 pushbuf;
diff --git a/drivers/gpu/drm/nouveau/core/include/engine/disp.h b/drivers/gpu/drm/nouveau/core/include/engine/disp.h
index 28da677..4b21fabf 100644
--- a/drivers/gpu/drm/nouveau/core/include/engine/disp.h
+++ b/drivers/gpu/drm/nouveau/core/include/engine/disp.h
@@ -44,5 +44,6 @@
extern struct nouveau_oclass nva3_disp_oclass;
extern struct nouveau_oclass nvd0_disp_oclass;
extern struct nouveau_oclass nve0_disp_oclass;
+extern struct nouveau_oclass nvf0_disp_oclass;
#endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index c33b13f..46c152f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -33,6 +33,7 @@
#include <engine/device.h>
#include <engine/disp.h>
+#include <engine/fifo.h>
#include <subdev/vm.h>
@@ -164,7 +165,7 @@
u32 arg0, arg1;
int ret;
- if (nouveau_noaccel)
+ if (nouveau_noaccel || !nouveau_fifo(device) /*XXX*/)
return;
/* initialise synchronisation routines */
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 7f0e6c3..3258873 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -2174,6 +2174,7 @@
nv50_display_create(struct drm_device *dev)
{
static const u16 oclass[] = {
+ NVF0_DISP_CLASS,
NVE0_DISP_CLASS,
NVD0_DISP_CLASS,
NVA3_DISP_CLASS,
diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c
index 46a9c37..fb441a7 100644
--- a/drivers/gpu/drm/radeon/atom.c
+++ b/drivers/gpu/drm/radeon/atom.c
@@ -1394,10 +1394,10 @@
firmware_usage = (struct _ATOM_VRAM_USAGE_BY_FIRMWARE *)(ctx->bios + data_offset);
DRM_DEBUG("atom firmware requested %08x %dkb\n",
- firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware,
- firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb);
+ le32_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware),
+ le16_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb));
- usage_bytes = firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb * 1024;
+ usage_bytes = le16_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb) * 1024;
}
ctx->scratch_size_bytes = 0;
if (usage_bytes == 0)
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 1531f16..105bafb 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -989,62 +989,10 @@
return r;
}
-static int evergreen_uvd_calc_post_div(unsigned target_freq,
- unsigned vco_freq,
- unsigned *div)
-{
- /* target larger than vco frequency ? */
- if (vco_freq < target_freq)
- return -1; /* forget it */
-
- /* Fclk = Fvco / PDIV */
- *div = vco_freq / target_freq;
-
- /* we alway need a frequency less than or equal the target */
- if ((vco_freq / *div) > target_freq)
- *div += 1;
-
- /* dividers above 5 must be even */
- if (*div > 5 && *div % 2)
- *div += 1;
-
- /* out of range ? */
- if (*div >= 128)
- return -1; /* forget it */
-
- return vco_freq / *div;
-}
-
-static int evergreen_uvd_send_upll_ctlreq(struct radeon_device *rdev)
-{
- unsigned i;
-
- /* assert UPLL_CTLREQ */
- WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_CTLREQ_MASK, ~UPLL_CTLREQ_MASK);
-
- /* wait for CTLACK and CTLACK2 to get asserted */
- for (i = 0; i < 100; ++i) {
- uint32_t mask = UPLL_CTLACK_MASK | UPLL_CTLACK2_MASK;
- if ((RREG32(CG_UPLL_FUNC_CNTL) & mask) == mask)
- break;
- mdelay(10);
- }
- if (i == 100)
- return -ETIMEDOUT;
-
- /* deassert UPLL_CTLREQ */
- WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_CTLREQ_MASK);
-
- return 0;
-}
-
int evergreen_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk)
{
/* start off with something large */
- int optimal_diff_score = 0x7FFFFFF;
- unsigned optimal_fb_div = 0, optimal_vclk_div = 0;
- unsigned optimal_dclk_div = 0, optimal_vco_freq = 0;
- unsigned vco_freq;
+ unsigned fb_div = 0, vclk_div = 0, dclk_div = 0;
int r;
/* bypass vclk and dclk with bclk */
@@ -1061,40 +1009,11 @@
return 0;
}
- /* loop through vco from low to high */
- for (vco_freq = 125000; vco_freq <= 250000; vco_freq += 100) {
- unsigned fb_div = vco_freq / rdev->clock.spll.reference_freq * 16384;
- int calc_clk, diff_score, diff_vclk, diff_dclk;
- unsigned vclk_div, dclk_div;
-
- /* fb div out of range ? */
- if (fb_div > 0x03FFFFFF)
- break; /* it can oly get worse */
-
- /* calc vclk with current vco freq. */
- calc_clk = evergreen_uvd_calc_post_div(vclk, vco_freq, &vclk_div);
- if (calc_clk == -1)
- break; /* vco is too big, it has to stop. */
- diff_vclk = vclk - calc_clk;
-
- /* calc dclk with current vco freq. */
- calc_clk = evergreen_uvd_calc_post_div(dclk, vco_freq, &dclk_div);
- if (calc_clk == -1)
- break; /* vco is too big, it has to stop. */
- diff_dclk = dclk - calc_clk;
-
- /* determine if this vco setting is better than current optimal settings */
- diff_score = abs(diff_vclk) + abs(diff_dclk);
- if (diff_score < optimal_diff_score) {
- optimal_fb_div = fb_div;
- optimal_vclk_div = vclk_div;
- optimal_dclk_div = dclk_div;
- optimal_vco_freq = vco_freq;
- optimal_diff_score = diff_score;
- if (optimal_diff_score == 0)
- break; /* it can't get better than this */
- }
- }
+ r = radeon_uvd_calc_upll_dividers(rdev, vclk, dclk, 125000, 250000,
+ 16384, 0x03FFFFFF, 0, 128, 5,
+ &fb_div, &vclk_div, &dclk_div);
+ if (r)
+ return r;
/* set VCO_MODE to 1 */
WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_VCO_MODE_MASK, ~UPLL_VCO_MODE_MASK);
@@ -1108,7 +1027,7 @@
mdelay(1);
- r = evergreen_uvd_send_upll_ctlreq(rdev);
+ r = radeon_uvd_send_upll_ctlreq(rdev, CG_UPLL_FUNC_CNTL);
if (r)
return r;
@@ -1119,19 +1038,19 @@
WREG32_P(CG_UPLL_SPREAD_SPECTRUM, 0, ~SSEN_MASK);
/* set feedback divider */
- WREG32_P(CG_UPLL_FUNC_CNTL_3, UPLL_FB_DIV(optimal_fb_div), ~UPLL_FB_DIV_MASK);
+ WREG32_P(CG_UPLL_FUNC_CNTL_3, UPLL_FB_DIV(fb_div), ~UPLL_FB_DIV_MASK);
/* set ref divider to 0 */
WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_REF_DIV_MASK);
- if (optimal_vco_freq < 187500)
+ if (fb_div < 307200)
WREG32_P(CG_UPLL_FUNC_CNTL_4, 0, ~UPLL_SPARE_ISPARE9);
else
WREG32_P(CG_UPLL_FUNC_CNTL_4, UPLL_SPARE_ISPARE9, ~UPLL_SPARE_ISPARE9);
/* set PDIV_A and PDIV_B */
WREG32_P(CG_UPLL_FUNC_CNTL_2,
- UPLL_PDIV_A(optimal_vclk_div) | UPLL_PDIV_B(optimal_dclk_div),
+ UPLL_PDIV_A(vclk_div) | UPLL_PDIV_B(dclk_div),
~(UPLL_PDIV_A_MASK | UPLL_PDIV_B_MASK));
/* give the PLL some time to settle */
@@ -1145,7 +1064,7 @@
/* switch from bypass mode to normal mode */
WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_BYPASS_EN_MASK);
- r = evergreen_uvd_send_upll_ctlreq(rdev);
+ r = radeon_uvd_send_upll_ctlreq(rdev, CG_UPLL_FUNC_CNTL);
if (r)
return r;
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h
index d9a0054..75c0563 100644
--- a/drivers/gpu/drm/radeon/evergreend.h
+++ b/drivers/gpu/drm/radeon/evergreend.h
@@ -59,7 +59,7 @@
# define UPLL_SLEEP_MASK 0x00000002
# define UPLL_BYPASS_EN_MASK 0x00000004
# define UPLL_CTLREQ_MASK 0x00000008
-# define UPLL_REF_DIV_MASK 0x001F0000
+# define UPLL_REF_DIV_MASK 0x003F0000
# define UPLL_VCO_MODE_MASK 0x00000200
# define UPLL_CTLACK_MASK 0x40000000
# define UPLL_CTLACK2_MASK 0x80000000
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index 7436b91..7969c0c 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -749,7 +749,8 @@
(rdev->pdev->device == 0x990F) ||
(rdev->pdev->device == 0x9910) ||
(rdev->pdev->device == 0x9917) ||
- (rdev->pdev->device == 0x9999)) {
+ (rdev->pdev->device == 0x9999) ||
+ (rdev->pdev->device == 0x999C)) {
rdev->config.cayman.max_simds_per_se = 6;
rdev->config.cayman.max_backends_per_se = 2;
} else if ((rdev->pdev->device == 0x9903) ||
@@ -758,7 +759,8 @@
(rdev->pdev->device == 0x990D) ||
(rdev->pdev->device == 0x990E) ||
(rdev->pdev->device == 0x9913) ||
- (rdev->pdev->device == 0x9918)) {
+ (rdev->pdev->device == 0x9918) ||
+ (rdev->pdev->device == 0x999D)) {
rdev->config.cayman.max_simds_per_se = 4;
rdev->config.cayman.max_backends_per_se = 2;
} else if ((rdev->pdev->device == 0x9919) ||
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h
index 6105b25..acb146c 100644
--- a/drivers/gpu/drm/radeon/r600d.h
+++ b/drivers/gpu/drm/radeon/r600d.h
@@ -1208,6 +1208,10 @@
#define UVD_CONTEXT_ID 0xf6f4
+# define UPLL_CTLREQ_MASK 0x00000008
+# define UPLL_CTLACK_MASK 0x40000000
+# define UPLL_CTLACK2_MASK 0x80000000
+
/*
* PM4
*/
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index d6c8cba..1442ce7 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -358,7 +358,8 @@
struct radeon_device *rdev;
struct drm_gem_object gem_base;
- struct ttm_bo_kmap_obj dma_buf_vmap;
+ struct ttm_bo_kmap_obj dma_buf_vmap;
+ pid_t pid;
};
#define gem_to_radeon_bo(gobj) container_of((gobj), struct radeon_bo, gem_base)
@@ -372,6 +373,8 @@
u32 tiling_flags;
};
+int radeon_gem_debugfs_init(struct radeon_device *rdev);
+
/* sub-allocation manager, it has to be protected by another lock.
* By conception this is an helper for other part of the driver
* like the indirect buffer or semaphore, which both have their
@@ -1159,6 +1162,17 @@
struct drm_file *filp);
int radeon_uvd_cs_parse(struct radeon_cs_parser *parser);
void radeon_uvd_note_usage(struct radeon_device *rdev);
+int radeon_uvd_calc_upll_dividers(struct radeon_device *rdev,
+ unsigned vclk, unsigned dclk,
+ unsigned vco_min, unsigned vco_max,
+ unsigned fb_factor, unsigned fb_mask,
+ unsigned pd_min, unsigned pd_max,
+ unsigned pd_even,
+ unsigned *optimal_fb_div,
+ unsigned *optimal_vclk_div,
+ unsigned *optimal_dclk_div);
+int radeon_uvd_send_upll_ctlreq(struct radeon_device *rdev,
+ unsigned cg_upll_func_cntl);
struct r600_audio {
int channels;
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index 0dd87c0..dea6f63c 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -2028,6 +2028,8 @@
num_modes = power_info->info.ucNumOfPowerModeEntries;
if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK)
num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK;
+ if (num_modes == 0)
+ return state_index;
rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * num_modes, GFP_KERNEL);
if (!rdev->pm.power_state)
return state_index;
@@ -2307,7 +2309,7 @@
rdev->pm.default_power_state_index = state_index;
rdev->pm.power_state[state_index].default_clock_mode =
&rdev->pm.power_state[state_index].clock_info[mode_index - 1];
- if (ASIC_IS_DCE5(rdev) && !(rdev->flags & RADEON_IS_IGP)) {
+ if ((rdev->family >= CHIP_BARTS) && !(rdev->flags & RADEON_IS_IGP)) {
/* NI chips post without MC ucode, so default clocks are strobe mode only */
rdev->pm.default_sclk = rdev->pm.power_state[state_index].clock_info[0].sclk;
rdev->pm.default_mclk = rdev->pm.power_state[state_index].clock_info[0].mclk;
@@ -2345,7 +2347,7 @@
sclk |= clock_info->rs780.ucLowEngineClockHigh << 16;
rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk;
}
- } else if (ASIC_IS_DCE6(rdev)) {
+ } else if (rdev->family >= CHIP_TAHITI) {
sclk = le16_to_cpu(clock_info->si.usEngineClockLow);
sclk |= clock_info->si.ucEngineClockHigh << 16;
mclk = le16_to_cpu(clock_info->si.usMemoryClockLow);
@@ -2358,7 +2360,7 @@
le16_to_cpu(clock_info->si.usVDDC);
rdev->pm.power_state[state_index].clock_info[mode_index].voltage.vddci =
le16_to_cpu(clock_info->si.usVDDCI);
- } else if (ASIC_IS_DCE4(rdev)) {
+ } else if (rdev->family >= CHIP_CEDAR) {
sclk = le16_to_cpu(clock_info->evergreen.usEngineClockLow);
sclk |= clock_info->evergreen.ucEngineClockHigh << 16;
mclk = le16_to_cpu(clock_info->evergreen.usMemoryClockLow);
@@ -2432,6 +2434,8 @@
power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController);
+ if (power_info->pplib.ucNumStates == 0)
+ return state_index;
rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) *
power_info->pplib.ucNumStates, GFP_KERNEL);
if (!rdev->pm.power_state)
@@ -2514,6 +2518,7 @@
int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
u16 data_offset;
u8 frev, crev;
+ u8 *power_state_offset;
if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
&frev, &crev, &data_offset))
@@ -2530,15 +2535,17 @@
non_clock_info_array = (struct _NonClockInfoArray *)
(mode_info->atom_context->bios + data_offset +
le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
+ if (state_array->ucNumEntries == 0)
+ return state_index;
rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) *
state_array->ucNumEntries, GFP_KERNEL);
if (!rdev->pm.power_state)
return state_index;
+ power_state_offset = (u8 *)state_array->states;
for (i = 0; i < state_array->ucNumEntries; i++) {
mode_index = 0;
- power_state = (union pplib_power_state *)&state_array->states[i];
- /* XXX this might be an inagua bug... */
- non_clock_array_index = i; /* power_state->v2.nonClockInfoIndex */
+ power_state = (union pplib_power_state *)power_state_offset;
+ non_clock_array_index = power_state->v2.nonClockInfoIndex;
non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
&non_clock_info_array->nonClockInfo[non_clock_array_index];
rdev->pm.power_state[i].clock_info = kzalloc(sizeof(struct radeon_pm_clock_info) *
@@ -2550,9 +2557,6 @@
if (power_state->v2.ucNumDPMLevels) {
for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
clock_array_index = power_state->v2.clockInfoIndex[j];
- /* XXX this might be an inagua bug... */
- if (clock_array_index >= clock_info_array->ucNumEntries)
- continue;
clock_info = (union pplib_clock_info *)
&clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize];
valid = radeon_atombios_parse_pplib_clock_info(rdev,
@@ -2574,6 +2578,7 @@
non_clock_info);
state_index++;
}
+ power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
}
/* if multiple clock modes, mark the lowest as no display */
for (i = 0; i < state_index; i++) {
@@ -2620,7 +2625,9 @@
default:
break;
}
- } else {
+ }
+
+ if (state_index == 0) {
rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state), GFP_KERNEL);
if (rdev->pm.power_state) {
rdev->pm.power_state[0].clock_info =
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 237b7a7..a8f6089 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -1178,6 +1178,11 @@
if (r)
DRM_ERROR("ib ring test failed (%d).\n", r);
+ r = radeon_gem_debugfs_init(rdev);
+ if (r) {
+ DRM_ERROR("registering gem debugfs failed (%d).\n", r);
+ }
+
if (rdev->flags & RADEON_IS_AGP && !rdev->accel_working) {
/* Acceleration not working on AGP card try again
* with fallback to PCI or PCIE GART
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c
index 1a699ce..5b937df 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -767,8 +767,8 @@
radeon_scratch_free(rdev, rdev->fence_drv[ring].scratch_reg);
if (rdev->wb.use_event || !radeon_ring_supports_scratch_reg(rdev, &rdev->ring[ring])) {
+ rdev->fence_drv[ring].scratch_reg = 0;
if (ring != R600_RING_TYPE_UVD_INDEX) {
- rdev->fence_drv[ring].scratch_reg = 0;
index = R600_WB_EVENT_OFFSET + ring * 4;
rdev->fence_drv[ring].cpu_addr = &rdev->wb.wb[index/4];
rdev->fence_drv[ring].gpu_addr = rdev->wb.gpu_addr +
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c
index fe5c1f6..aa79603 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -84,6 +84,7 @@
return r;
}
*obj = &robj->gem_base;
+ robj->pid = task_pid_nr(current);
mutex_lock(&rdev->gem.mutex);
list_add_tail(&robj->list, &rdev->gem.objects);
@@ -575,3 +576,52 @@
{
return drm_gem_handle_delete(file_priv, handle);
}
+
+#if defined(CONFIG_DEBUG_FS)
+static int radeon_debugfs_gem_info(struct seq_file *m, void *data)
+{
+ struct drm_info_node *node = (struct drm_info_node *)m->private;
+ struct drm_device *dev = node->minor->dev;
+ struct radeon_device *rdev = dev->dev_private;
+ struct radeon_bo *rbo;
+ unsigned i = 0;
+
+ mutex_lock(&rdev->gem.mutex);
+ list_for_each_entry(rbo, &rdev->gem.objects, list) {
+ unsigned domain;
+ const char *placement;
+
+ domain = radeon_mem_type_to_domain(rbo->tbo.mem.mem_type);
+ switch (domain) {
+ case RADEON_GEM_DOMAIN_VRAM:
+ placement = "VRAM";
+ break;
+ case RADEON_GEM_DOMAIN_GTT:
+ placement = " GTT";
+ break;
+ case RADEON_GEM_DOMAIN_CPU:
+ default:
+ placement = " CPU";
+ break;
+ }
+ seq_printf(m, "bo[0x%08x] %8ldkB %8ldMB %s pid %8ld\n",
+ i, radeon_bo_size(rbo) >> 10, radeon_bo_size(rbo) >> 20,
+ placement, (unsigned long)rbo->pid);
+ i++;
+ }
+ mutex_unlock(&rdev->gem.mutex);
+ return 0;
+}
+
+static struct drm_info_list radeon_debugfs_gem_list[] = {
+ {"radeon_gem_info", &radeon_debugfs_gem_info, 0, NULL},
+};
+#endif
+
+int radeon_gem_debugfs_init(struct radeon_device *rdev)
+{
+#if defined(CONFIG_DEBUG_FS)
+ return radeon_debugfs_add_files(rdev, radeon_debugfs_gem_list, 1);
+#endif
+ return 0;
+}
diff --git a/drivers/gpu/drm/radeon/radeon_sa.c b/drivers/gpu/drm/radeon/radeon_sa.c
index cb80099..0abe5a9 100644
--- a/drivers/gpu/drm/radeon/radeon_sa.c
+++ b/drivers/gpu/drm/radeon/radeon_sa.c
@@ -64,7 +64,7 @@
}
r = radeon_bo_create(rdev, size, RADEON_GPU_PAGE_SIZE, true,
- RADEON_GEM_DOMAIN_CPU, NULL, &sa_manager->bo);
+ domain, NULL, &sa_manager->bo);
if (r) {
dev_err(rdev->dev, "(%d) failed to allocate bo for manager\n", r);
return r;
diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
index 0312a7f..906e5c0 100644
--- a/drivers/gpu/drm/radeon/radeon_uvd.c
+++ b/drivers/gpu/drm/radeon/radeon_uvd.c
@@ -692,3 +692,140 @@
if (set_clocks)
radeon_set_uvd_clocks(rdev, 53300, 40000);
}
+
+static unsigned radeon_uvd_calc_upll_post_div(unsigned vco_freq,
+ unsigned target_freq,
+ unsigned pd_min,
+ unsigned pd_even)
+{
+ unsigned post_div = vco_freq / target_freq;
+
+ /* adjust to post divider minimum value */
+ if (post_div < pd_min)
+ post_div = pd_min;
+
+ /* we alway need a frequency less than or equal the target */
+ if ((vco_freq / post_div) > target_freq)
+ post_div += 1;
+
+ /* post dividers above a certain value must be even */
+ if (post_div > pd_even && post_div % 2)
+ post_div += 1;
+
+ return post_div;
+}
+
+/**
+ * radeon_uvd_calc_upll_dividers - calc UPLL clock dividers
+ *
+ * @rdev: radeon_device pointer
+ * @vclk: wanted VCLK
+ * @dclk: wanted DCLK
+ * @vco_min: minimum VCO frequency
+ * @vco_max: maximum VCO frequency
+ * @fb_factor: factor to multiply vco freq with
+ * @fb_mask: limit and bitmask for feedback divider
+ * @pd_min: post divider minimum
+ * @pd_max: post divider maximum
+ * @pd_even: post divider must be even above this value
+ * @optimal_fb_div: resulting feedback divider
+ * @optimal_vclk_div: resulting vclk post divider
+ * @optimal_dclk_div: resulting dclk post divider
+ *
+ * Calculate dividers for UVDs UPLL (R6xx-SI, except APUs).
+ * Returns zero on success -EINVAL on error.
+ */
+int radeon_uvd_calc_upll_dividers(struct radeon_device *rdev,
+ unsigned vclk, unsigned dclk,
+ unsigned vco_min, unsigned vco_max,
+ unsigned fb_factor, unsigned fb_mask,
+ unsigned pd_min, unsigned pd_max,
+ unsigned pd_even,
+ unsigned *optimal_fb_div,
+ unsigned *optimal_vclk_div,
+ unsigned *optimal_dclk_div)
+{
+ unsigned vco_freq, ref_freq = rdev->clock.spll.reference_freq;
+
+ /* start off with something large */
+ unsigned optimal_score = ~0;
+
+ /* loop through vco from low to high */
+ vco_min = max(max(vco_min, vclk), dclk);
+ for (vco_freq = vco_min; vco_freq <= vco_max; vco_freq += 100) {
+
+ uint64_t fb_div = (uint64_t)vco_freq * fb_factor;
+ unsigned vclk_div, dclk_div, score;
+
+ do_div(fb_div, ref_freq);
+
+ /* fb div out of range ? */
+ if (fb_div > fb_mask)
+ break; /* it can oly get worse */
+
+ fb_div &= fb_mask;
+
+ /* calc vclk divider with current vco freq */
+ vclk_div = radeon_uvd_calc_upll_post_div(vco_freq, vclk,
+ pd_min, pd_even);
+ if (vclk_div > pd_max)
+ break; /* vco is too big, it has to stop */
+
+ /* calc dclk divider with current vco freq */
+ dclk_div = radeon_uvd_calc_upll_post_div(vco_freq, dclk,
+ pd_min, pd_even);
+ if (vclk_div > pd_max)
+ break; /* vco is too big, it has to stop */
+
+ /* calc score with current vco freq */
+ score = vclk - (vco_freq / vclk_div) + dclk - (vco_freq / dclk_div);
+
+ /* determine if this vco setting is better than current optimal settings */
+ if (score < optimal_score) {
+ *optimal_fb_div = fb_div;
+ *optimal_vclk_div = vclk_div;
+ *optimal_dclk_div = dclk_div;
+ optimal_score = score;
+ if (optimal_score == 0)
+ break; /* it can't get better than this */
+ }
+ }
+
+ /* did we found a valid setup ? */
+ if (optimal_score == ~0)
+ return -EINVAL;
+
+ return 0;
+}
+
+int radeon_uvd_send_upll_ctlreq(struct radeon_device *rdev,
+ unsigned cg_upll_func_cntl)
+{
+ unsigned i;
+
+ /* make sure UPLL_CTLREQ is deasserted */
+ WREG32_P(cg_upll_func_cntl, 0, ~UPLL_CTLREQ_MASK);
+
+ mdelay(10);
+
+ /* assert UPLL_CTLREQ */
+ WREG32_P(cg_upll_func_cntl, UPLL_CTLREQ_MASK, ~UPLL_CTLREQ_MASK);
+
+ /* wait for CTLACK and CTLACK2 to get asserted */
+ for (i = 0; i < 100; ++i) {
+ uint32_t mask = UPLL_CTLACK_MASK | UPLL_CTLACK2_MASK;
+ if ((RREG32(cg_upll_func_cntl) & mask) == mask)
+ break;
+ mdelay(10);
+ }
+
+ /* deassert UPLL_CTLREQ */
+ WREG32_P(cg_upll_func_cntl, 0, ~UPLL_CTLREQ_MASK);
+
+ if (i == 100) {
+ DRM_ERROR("Timeout setting UVD clocks!\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index 91530d4..83f612a 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -44,56 +44,9 @@
static void rv770_pcie_gen2_enable(struct radeon_device *rdev);
int evergreen_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
-static int rv770_uvd_calc_post_div(unsigned target_freq,
- unsigned vco_freq,
- unsigned *div)
-{
- /* Fclk = Fvco / PDIV */
- *div = vco_freq / target_freq;
-
- /* we alway need a frequency less than or equal the target */
- if ((vco_freq / *div) > target_freq)
- *div += 1;
-
- /* out of range ? */
- if (*div > 30)
- return -1; /* forget it */
-
- *div -= 1;
- return vco_freq / (*div + 1);
-}
-
-static int rv770_uvd_send_upll_ctlreq(struct radeon_device *rdev)
-{
- unsigned i;
-
- /* assert UPLL_CTLREQ */
- WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_CTLREQ_MASK, ~UPLL_CTLREQ_MASK);
-
- /* wait for CTLACK and CTLACK2 to get asserted */
- for (i = 0; i < 100; ++i) {
- uint32_t mask = UPLL_CTLACK_MASK | UPLL_CTLACK2_MASK;
- if ((RREG32(CG_UPLL_FUNC_CNTL) & mask) == mask)
- break;
- mdelay(10);
- }
- if (i == 100)
- return -ETIMEDOUT;
-
- /* deassert UPLL_CTLREQ */
- WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_CTLREQ_MASK);
-
- return 0;
-}
-
int rv770_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk)
{
- /* start off with something large */
- int optimal_diff_score = 0x7FFFFFF;
- unsigned optimal_fb_div = 0, optimal_vclk_div = 0;
- unsigned optimal_dclk_div = 0, optimal_vco_freq = 0;
- unsigned vco_freq, vco_min = 50000, vco_max = 160000;
- unsigned ref_freq = rdev->clock.spll.reference_freq;
+ unsigned fb_div = 0, vclk_div = 0, dclk_div = 0;
int r;
/* RV740 uses evergreen uvd clk programming */
@@ -111,44 +64,15 @@
return 0;
}
- /* loop through vco from low to high */
- vco_min = max(max(vco_min, vclk), dclk);
- for (vco_freq = vco_min; vco_freq <= vco_max; vco_freq += 500) {
- uint64_t fb_div = (uint64_t)vco_freq * 43663;
- int calc_clk, diff_score, diff_vclk, diff_dclk;
- unsigned vclk_div, dclk_div;
+ r = radeon_uvd_calc_upll_dividers(rdev, vclk, dclk, 50000, 160000,
+ 43663, 0x03FFFFFE, 1, 30, ~0,
+ &fb_div, &vclk_div, &dclk_div);
+ if (r)
+ return r;
- do_div(fb_div, ref_freq);
- fb_div |= 1;
-
- /* fb div out of range ? */
- if (fb_div > 0x03FFFFFF)
- break; /* it can oly get worse */
-
- /* calc vclk with current vco freq. */
- calc_clk = rv770_uvd_calc_post_div(vclk, vco_freq, &vclk_div);
- if (calc_clk == -1)
- break; /* vco is too big, it has to stop. */
- diff_vclk = vclk - calc_clk;
-
- /* calc dclk with current vco freq. */
- calc_clk = rv770_uvd_calc_post_div(dclk, vco_freq, &dclk_div);
- if (calc_clk == -1)
- break; /* vco is too big, it has to stop. */
- diff_dclk = dclk - calc_clk;
-
- /* determine if this vco setting is better than current optimal settings */
- diff_score = abs(diff_vclk) + abs(diff_dclk);
- if (diff_score < optimal_diff_score) {
- optimal_fb_div = fb_div;
- optimal_vclk_div = vclk_div;
- optimal_dclk_div = dclk_div;
- optimal_vco_freq = vco_freq;
- optimal_diff_score = diff_score;
- if (optimal_diff_score == 0)
- break; /* it can't get better than this */
- }
- }
+ fb_div |= 1;
+ vclk_div -= 1;
+ dclk_div -= 1;
/* set UPLL_FB_DIV to 0x50000 */
WREG32_P(CG_UPLL_FUNC_CNTL_3, UPLL_FB_DIV(0x50000), ~UPLL_FB_DIV_MASK);
@@ -160,7 +84,7 @@
WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~UPLL_BYPASS_EN_MASK);
WREG32_P(CG_UPLL_FUNC_CNTL_3, UPLL_FB_DIV(1), ~UPLL_FB_DIV(1));
- r = rv770_uvd_send_upll_ctlreq(rdev);
+ r = radeon_uvd_send_upll_ctlreq(rdev, CG_UPLL_FUNC_CNTL);
if (r)
return r;
@@ -170,13 +94,13 @@
/* set the required FB_DIV, REF_DIV, Post divder values */
WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_REF_DIV(1), ~UPLL_REF_DIV_MASK);
WREG32_P(CG_UPLL_FUNC_CNTL_2,
- UPLL_SW_HILEN(optimal_vclk_div >> 1) |
- UPLL_SW_LOLEN((optimal_vclk_div >> 1) + (optimal_vclk_div & 1)) |
- UPLL_SW_HILEN2(optimal_dclk_div >> 1) |
- UPLL_SW_LOLEN2((optimal_dclk_div >> 1) + (optimal_dclk_div & 1)),
+ UPLL_SW_HILEN(vclk_div >> 1) |
+ UPLL_SW_LOLEN((vclk_div >> 1) + (vclk_div & 1)) |
+ UPLL_SW_HILEN2(dclk_div >> 1) |
+ UPLL_SW_LOLEN2((dclk_div >> 1) + (dclk_div & 1)),
~UPLL_SW_MASK);
- WREG32_P(CG_UPLL_FUNC_CNTL_3, UPLL_FB_DIV(optimal_fb_div),
+ WREG32_P(CG_UPLL_FUNC_CNTL_3, UPLL_FB_DIV(fb_div),
~UPLL_FB_DIV_MASK);
/* give the PLL some time to settle */
@@ -191,7 +115,7 @@
WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_BYPASS_EN_MASK);
WREG32_P(CG_UPLL_FUNC_CNTL_3, 0, ~UPLL_FB_DIV(1));
- r = rv770_uvd_send_upll_ctlreq(rdev);
+ r = radeon_uvd_send_upll_ctlreq(rdev, CG_UPLL_FUNC_CNTL);
if (r)
return r;
diff --git a/drivers/gpu/drm/radeon/rv770d.h b/drivers/gpu/drm/radeon/rv770d.h
index 6a52b20..85b1626 100644
--- a/drivers/gpu/drm/radeon/rv770d.h
+++ b/drivers/gpu/drm/radeon/rv770d.h
@@ -45,7 +45,7 @@
# define UPLL_BYPASS_EN_MASK 0x00000004
# define UPLL_CTLREQ_MASK 0x00000008
# define UPLL_REF_DIV(x) ((x) << 16)
-# define UPLL_REF_DIV_MASK 0x001F0000
+# define UPLL_REF_DIV_MASK 0x003F0000
# define UPLL_CTLACK_MASK 0x40000000
# define UPLL_CTLACK2_MASK 0x80000000
#define CG_UPLL_FUNC_CNTL_2 0x71c
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index fe6b14e..f0b6c2f 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -5415,62 +5415,9 @@
return clock;
}
-static int si_uvd_calc_post_div(unsigned target_freq,
- unsigned vco_freq,
- unsigned *div)
-{
- /* target larger than vco frequency ? */
- if (vco_freq < target_freq)
- return -1; /* forget it */
-
- /* Fclk = Fvco / PDIV */
- *div = vco_freq / target_freq;
-
- /* we alway need a frequency less than or equal the target */
- if ((vco_freq / *div) > target_freq)
- *div += 1;
-
- /* dividers above 5 must be even */
- if (*div > 5 && *div % 2)
- *div += 1;
-
- /* out of range ? */
- if (*div >= 128)
- return -1; /* forget it */
-
- return vco_freq / *div;
-}
-
-static int si_uvd_send_upll_ctlreq(struct radeon_device *rdev)
-{
- unsigned i;
-
- /* assert UPLL_CTLREQ */
- WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_CTLREQ_MASK, ~UPLL_CTLREQ_MASK);
-
- /* wait for CTLACK and CTLACK2 to get asserted */
- for (i = 0; i < 100; ++i) {
- uint32_t mask = UPLL_CTLACK_MASK | UPLL_CTLACK2_MASK;
- if ((RREG32(CG_UPLL_FUNC_CNTL) & mask) == mask)
- break;
- mdelay(10);
- }
- if (i == 100)
- return -ETIMEDOUT;
-
- /* deassert UPLL_CTLREQ */
- WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_CTLREQ_MASK);
-
- return 0;
-}
-
int si_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk)
{
- /* start off with something large */
- int optimal_diff_score = 0x7FFFFFF;
- unsigned optimal_fb_div = 0, optimal_vclk_div = 0;
- unsigned optimal_dclk_div = 0, optimal_vco_freq = 0;
- unsigned vco_freq;
+ unsigned fb_div = 0, vclk_div = 0, dclk_div = 0;
int r;
/* bypass vclk and dclk with bclk */
@@ -5487,40 +5434,11 @@
return 0;
}
- /* loop through vco from low to high */
- for (vco_freq = 125000; vco_freq <= 250000; vco_freq += 100) {
- unsigned fb_div = vco_freq / rdev->clock.spll.reference_freq * 16384;
- int calc_clk, diff_score, diff_vclk, diff_dclk;
- unsigned vclk_div, dclk_div;
-
- /* fb div out of range ? */
- if (fb_div > 0x03FFFFFF)
- break; /* it can oly get worse */
-
- /* calc vclk with current vco freq. */
- calc_clk = si_uvd_calc_post_div(vclk, vco_freq, &vclk_div);
- if (calc_clk == -1)
- break; /* vco is too big, it has to stop. */
- diff_vclk = vclk - calc_clk;
-
- /* calc dclk with current vco freq. */
- calc_clk = si_uvd_calc_post_div(dclk, vco_freq, &dclk_div);
- if (calc_clk == -1)
- break; /* vco is too big, it has to stop. */
- diff_dclk = dclk - calc_clk;
-
- /* determine if this vco setting is better than current optimal settings */
- diff_score = abs(diff_vclk) + abs(diff_dclk);
- if (diff_score < optimal_diff_score) {
- optimal_fb_div = fb_div;
- optimal_vclk_div = vclk_div;
- optimal_dclk_div = dclk_div;
- optimal_vco_freq = vco_freq;
- optimal_diff_score = diff_score;
- if (optimal_diff_score == 0)
- break; /* it can't get better than this */
- }
- }
+ r = radeon_uvd_calc_upll_dividers(rdev, vclk, dclk, 125000, 250000,
+ 16384, 0x03FFFFFF, 0, 128, 5,
+ &fb_div, &vclk_div, &dclk_div);
+ if (r)
+ return r;
/* set RESET_ANTI_MUX to 0 */
WREG32_P(CG_UPLL_FUNC_CNTL_5, 0, ~RESET_ANTI_MUX_MASK);
@@ -5537,7 +5455,7 @@
mdelay(1);
- r = si_uvd_send_upll_ctlreq(rdev);
+ r = radeon_uvd_send_upll_ctlreq(rdev, CG_UPLL_FUNC_CNTL);
if (r)
return r;
@@ -5548,19 +5466,19 @@
WREG32_P(CG_UPLL_SPREAD_SPECTRUM, 0, ~SSEN_MASK);
/* set feedback divider */
- WREG32_P(CG_UPLL_FUNC_CNTL_3, UPLL_FB_DIV(optimal_fb_div), ~UPLL_FB_DIV_MASK);
+ WREG32_P(CG_UPLL_FUNC_CNTL_3, UPLL_FB_DIV(fb_div), ~UPLL_FB_DIV_MASK);
/* set ref divider to 0 */
WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_REF_DIV_MASK);
- if (optimal_vco_freq < 187500)
+ if (fb_div < 307200)
WREG32_P(CG_UPLL_FUNC_CNTL_4, 0, ~UPLL_SPARE_ISPARE9);
else
WREG32_P(CG_UPLL_FUNC_CNTL_4, UPLL_SPARE_ISPARE9, ~UPLL_SPARE_ISPARE9);
/* set PDIV_A and PDIV_B */
WREG32_P(CG_UPLL_FUNC_CNTL_2,
- UPLL_PDIV_A(optimal_vclk_div) | UPLL_PDIV_B(optimal_dclk_div),
+ UPLL_PDIV_A(vclk_div) | UPLL_PDIV_B(dclk_div),
~(UPLL_PDIV_A_MASK | UPLL_PDIV_B_MASK));
/* give the PLL some time to settle */
@@ -5574,7 +5492,7 @@
/* switch from bypass mode to normal mode */
WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_BYPASS_EN_MASK);
- r = si_uvd_send_upll_ctlreq(rdev);
+ r = radeon_uvd_send_upll_ctlreq(rdev, CG_UPLL_FUNC_CNTL);
if (r)
return r;
diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h
index 042b91d..222877b 100644
--- a/drivers/gpu/drm/radeon/sid.h
+++ b/drivers/gpu/drm/radeon/sid.h
@@ -36,7 +36,7 @@
# define UPLL_BYPASS_EN_MASK 0x00000004
# define UPLL_CTLREQ_MASK 0x00000008
# define UPLL_VCO_MODE_MASK 0x00000600
-# define UPLL_REF_DIV_MASK 0x001F0000
+# define UPLL_REF_DIV_MASK 0x003F0000
# define UPLL_CTLACK_MASK 0x40000000
# define UPLL_CTLACK2_MASK 0x80000000
#define CG_UPLL_FUNC_CNTL_2 0x638
diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile
index 5ea7cb9..296e5c5 100644
--- a/drivers/video/omap2/Makefile
+++ b/drivers/video/omap2/Makefile
@@ -1,5 +1,5 @@
obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
obj-$(CONFIG_OMAP2_DSS) += dss/
-obj-$(CONFIG_FB_OMAP2) += omapfb/
obj-y += displays/
+obj-$(CONFIG_FB_OMAP2) += omapfb/
diff --git a/drivers/video/omap2/displays/panel-tfp410.c b/drivers/video/omap2/displays/panel-tfp410.c
index a1dba868..46039c4 100644
--- a/drivers/video/omap2/displays/panel-tfp410.c
+++ b/drivers/video/omap2/displays/panel-tfp410.c
@@ -135,7 +135,7 @@
if (!adapter) {
dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n",
i2c_bus_num);
- return -EINVAL;
+ return -EPROBE_DEFER;
}
ddata->i2c_adapter = adapter;
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index e93c4de..757b57f 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -520,7 +520,7 @@
}
EXPORT_SYMBOL(omapdss_dpi_set_data_lines);
-static int __init dpi_verify_dsi_pll(struct platform_device *dsidev)
+static int dpi_verify_dsi_pll(struct platform_device *dsidev)
{
int r;
@@ -572,7 +572,7 @@
}
}
-static int __init dpi_init_display(struct omap_dss_device *dssdev)
+static int dpi_init_display(struct omap_dss_device *dssdev)
{
struct platform_device *dsidev;
@@ -607,7 +607,7 @@
return 0;
}
-static struct omap_dss_device * __init dpi_find_dssdev(struct platform_device *pdev)
+static struct omap_dss_device *dpi_find_dssdev(struct platform_device *pdev)
{
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
const char *def_disp_name = omapdss_get_default_display_name();
@@ -635,7 +635,7 @@
return def_dssdev;
}
-static void __init dpi_probe_pdata(struct platform_device *dpidev)
+static int dpi_probe_pdata(struct platform_device *dpidev)
{
struct omap_dss_device *plat_dssdev;
struct omap_dss_device *dssdev;
@@ -644,11 +644,11 @@
plat_dssdev = dpi_find_dssdev(dpidev);
if (!plat_dssdev)
- return;
+ return 0;
dssdev = dss_alloc_and_init_device(&dpidev->dev);
if (!dssdev)
- return;
+ return -ENOMEM;
dss_copy_device_pdata(dssdev, plat_dssdev);
@@ -656,7 +656,7 @@
if (r) {
DSSERR("device %s init failed: %d\n", dssdev->name, r);
dss_put_device(dssdev);
- return;
+ return r;
}
r = omapdss_output_set_device(&dpi.output, dssdev);
@@ -664,7 +664,7 @@
DSSERR("failed to connect output to new device: %s\n",
dssdev->name);
dss_put_device(dssdev);
- return;
+ return r;
}
r = dss_add_device(dssdev);
@@ -672,11 +672,13 @@
DSSERR("device %s register failed: %d\n", dssdev->name, r);
omapdss_output_unset_device(&dpi.output);
dss_put_device(dssdev);
- return;
+ return r;
}
+
+ return 0;
}
-static void __init dpi_init_output(struct platform_device *pdev)
+static void dpi_init_output(struct platform_device *pdev)
{
struct omap_dss_output *out = &dpi.output;
@@ -696,13 +698,19 @@
dss_unregister_output(out);
}
-static int __init omap_dpi_probe(struct platform_device *pdev)
+static int omap_dpi_probe(struct platform_device *pdev)
{
+ int r;
+
mutex_init(&dpi.lock);
dpi_init_output(pdev);
- dpi_probe_pdata(pdev);
+ r = dpi_probe_pdata(pdev);
+ if (r) {
+ dpi_uninit_output(pdev);
+ return r;
+ }
return 0;
}
@@ -717,6 +725,7 @@
}
static struct platform_driver omap_dpi_driver = {
+ .probe = omap_dpi_probe,
.remove = __exit_p(omap_dpi_remove),
.driver = {
.name = "omapdss_dpi",
@@ -726,7 +735,7 @@
int __init dpi_init_platform_driver(void)
{
- return platform_driver_probe(&omap_dpi_driver, omap_dpi_probe);
+ return platform_driver_register(&omap_dpi_driver);
}
void __exit dpi_uninit_platform_driver(void)
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 9b1c5ec..a73dedc 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -5225,7 +5225,7 @@
}
}
-static int __init dsi_init_display(struct omap_dss_device *dssdev)
+static int dsi_init_display(struct omap_dss_device *dssdev)
{
struct platform_device *dsidev =
dsi_get_dsidev_from_id(dssdev->phy.dsi.module);
@@ -5366,7 +5366,7 @@
return 0;
}
-static struct omap_dss_device * __init dsi_find_dssdev(struct platform_device *pdev)
+static struct omap_dss_device *dsi_find_dssdev(struct platform_device *pdev)
{
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
struct dsi_data *dsi = dsi_get_dsidrv_data(pdev);
@@ -5398,7 +5398,7 @@
return def_dssdev;
}
-static void __init dsi_probe_pdata(struct platform_device *dsidev)
+static int dsi_probe_pdata(struct platform_device *dsidev)
{
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
struct omap_dss_device *plat_dssdev;
@@ -5408,11 +5408,11 @@
plat_dssdev = dsi_find_dssdev(dsidev);
if (!plat_dssdev)
- return;
+ return 0;
dssdev = dss_alloc_and_init_device(&dsidev->dev);
if (!dssdev)
- return;
+ return -ENOMEM;
dss_copy_device_pdata(dssdev, plat_dssdev);
@@ -5420,7 +5420,7 @@
if (r) {
DSSERR("device %s init failed: %d\n", dssdev->name, r);
dss_put_device(dssdev);
- return;
+ return r;
}
r = omapdss_output_set_device(&dsi->output, dssdev);
@@ -5428,7 +5428,7 @@
DSSERR("failed to connect output to new device: %s\n",
dssdev->name);
dss_put_device(dssdev);
- return;
+ return r;
}
r = dss_add_device(dssdev);
@@ -5436,11 +5436,13 @@
DSSERR("device %s register failed: %d\n", dssdev->name, r);
omapdss_output_unset_device(&dsi->output);
dss_put_device(dssdev);
- return;
+ return r;
}
+
+ return 0;
}
-static void __init dsi_init_output(struct platform_device *dsidev)
+static void dsi_init_output(struct platform_device *dsidev)
{
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
struct omap_dss_output *out = &dsi->output;
@@ -5456,7 +5458,7 @@
dss_register_output(out);
}
-static void __exit dsi_uninit_output(struct platform_device *dsidev)
+static void dsi_uninit_output(struct platform_device *dsidev)
{
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
struct omap_dss_output *out = &dsi->output;
@@ -5465,7 +5467,7 @@
}
/* DSI1 HW IP initialisation */
-static int __init omap_dsihw_probe(struct platform_device *dsidev)
+static int omap_dsihw_probe(struct platform_device *dsidev)
{
u32 rev;
int r, i;
@@ -5561,7 +5563,13 @@
dsi_init_output(dsidev);
- dsi_probe_pdata(dsidev);
+ r = dsi_probe_pdata(dsidev);
+ if (r) {
+ dsi_runtime_put(dsidev);
+ dsi_uninit_output(dsidev);
+ pm_runtime_disable(&dsidev->dev);
+ return r;
+ }
dsi_runtime_put(dsidev);
@@ -5632,6 +5640,7 @@
};
static struct platform_driver omap_dsihw_driver = {
+ .probe = omap_dsihw_probe,
.remove = __exit_p(omap_dsihw_remove),
.driver = {
.name = "omapdss_dsi",
@@ -5642,7 +5651,7 @@
int __init dsi_init_platform_driver(void)
{
- return platform_driver_probe(&omap_dsihw_driver, omap_dsihw_probe);
+ return platform_driver_register(&omap_dsihw_driver);
}
void __exit dsi_uninit_platform_driver(void)
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index faaf358..8475893 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -277,6 +277,12 @@
void sdi_uninit_platform_driver(void) __exit;
/* DSI */
+
+typedef bool (*dsi_pll_calc_func)(int regn, int regm, unsigned long fint,
+ unsigned long pll, void *data);
+typedef bool (*dsi_hsdiv_calc_func)(int regm_dispc, unsigned long dispc,
+ void *data);
+
#ifdef CONFIG_OMAP2_DSS_DSI
struct dentry;
@@ -295,10 +301,6 @@
unsigned long dsi_get_pll_clkin(struct platform_device *dsidev);
-typedef bool (*dsi_pll_calc_func)(int regn, int regm, unsigned long fint,
- unsigned long pll, void *data);
-typedef bool (*dsi_hsdiv_calc_func)(int regm_dispc, unsigned long dispc,
- void *data);
bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll,
unsigned long out_min, dsi_hsdiv_calc_func func, void *data);
bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin,
@@ -358,6 +360,27 @@
{
return NULL;
}
+
+static inline unsigned long dsi_get_pll_clkin(struct platform_device *dsidev)
+{
+ return 0;
+}
+
+static inline bool dsi_hsdiv_calc(struct platform_device *dsidev,
+ unsigned long pll, unsigned long out_min,
+ dsi_hsdiv_calc_func func, void *data)
+{
+ return false;
+}
+
+static inline bool dsi_pll_calc(struct platform_device *dsidev,
+ unsigned long clkin,
+ unsigned long pll_min, unsigned long pll_max,
+ dsi_pll_calc_func func, void *data)
+{
+ return false;
+}
+
#endif
/* DPI */
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index 7939309..17f4d55 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -328,7 +328,7 @@
WARN_ON(r < 0 && r != -ENOSYS);
}
-static int __init hdmi_init_display(struct omap_dss_device *dssdev)
+static int hdmi_init_display(struct omap_dss_device *dssdev)
{
int r;
@@ -954,7 +954,7 @@
#endif
-static struct omap_dss_device * __init hdmi_find_dssdev(struct platform_device *pdev)
+static struct omap_dss_device *hdmi_find_dssdev(struct platform_device *pdev)
{
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
const char *def_disp_name = omapdss_get_default_display_name();
@@ -982,7 +982,7 @@
return def_dssdev;
}
-static void __init hdmi_probe_pdata(struct platform_device *pdev)
+static int hdmi_probe_pdata(struct platform_device *pdev)
{
struct omap_dss_device *plat_dssdev;
struct omap_dss_device *dssdev;
@@ -992,11 +992,11 @@
plat_dssdev = hdmi_find_dssdev(pdev);
if (!plat_dssdev)
- return;
+ return 0;
dssdev = dss_alloc_and_init_device(&pdev->dev);
if (!dssdev)
- return;
+ return -ENOMEM;
dss_copy_device_pdata(dssdev, plat_dssdev);
@@ -1010,7 +1010,7 @@
if (r) {
DSSERR("device %s init failed: %d\n", dssdev->name, r);
dss_put_device(dssdev);
- return;
+ return r;
}
r = omapdss_output_set_device(&hdmi.output, dssdev);
@@ -1018,7 +1018,7 @@
DSSERR("failed to connect output to new device: %s\n",
dssdev->name);
dss_put_device(dssdev);
- return;
+ return r;
}
r = dss_add_device(dssdev);
@@ -1027,11 +1027,13 @@
omapdss_output_unset_device(&hdmi.output);
hdmi_uninit_display(dssdev);
dss_put_device(dssdev);
- return;
+ return r;
}
+
+ return 0;
}
-static void __init hdmi_init_output(struct platform_device *pdev)
+static void hdmi_init_output(struct platform_device *pdev)
{
struct omap_dss_output *out = &hdmi.output;
@@ -1052,7 +1054,7 @@
}
/* HDMI HW IP initialisation */
-static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
+static int omapdss_hdmihw_probe(struct platform_device *pdev)
{
struct resource *res;
int r;
@@ -1096,7 +1098,13 @@
dss_debugfs_create_file("hdmi", hdmi_dump_regs);
- hdmi_probe_pdata(pdev);
+ r = hdmi_probe_pdata(pdev);
+ if (r) {
+ hdmi_panel_exit();
+ hdmi_uninit_output(pdev);
+ pm_runtime_disable(&pdev->dev);
+ return r;
+ }
return 0;
}
@@ -1151,6 +1159,7 @@
};
static struct platform_driver omapdss_hdmihw_driver = {
+ .probe = omapdss_hdmihw_probe,
.remove = __exit_p(omapdss_hdmihw_remove),
.driver = {
.name = "omapdss_hdmi",
@@ -1161,7 +1170,7 @@
int __init hdmi_init_platform_driver(void)
{
- return platform_driver_probe(&omapdss_hdmihw_driver, omapdss_hdmihw_probe);
+ return platform_driver_register(&omapdss_hdmihw_driver);
}
void __exit hdmi_uninit_platform_driver(void)
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index 1a691bb..1a17dd1 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -943,13 +943,13 @@
}
EXPORT_SYMBOL(omapdss_rfbi_display_disable);
-static int __init rfbi_init_display(struct omap_dss_device *dssdev)
+static int rfbi_init_display(struct omap_dss_device *dssdev)
{
rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev;
return 0;
}
-static struct omap_dss_device * __init rfbi_find_dssdev(struct platform_device *pdev)
+static struct omap_dss_device *rfbi_find_dssdev(struct platform_device *pdev)
{
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
const char *def_disp_name = omapdss_get_default_display_name();
@@ -977,7 +977,7 @@
return def_dssdev;
}
-static void __init rfbi_probe_pdata(struct platform_device *rfbidev)
+static int rfbi_probe_pdata(struct platform_device *rfbidev)
{
struct omap_dss_device *plat_dssdev;
struct omap_dss_device *dssdev;
@@ -986,11 +986,11 @@
plat_dssdev = rfbi_find_dssdev(rfbidev);
if (!plat_dssdev)
- return;
+ return 0;
dssdev = dss_alloc_and_init_device(&rfbidev->dev);
if (!dssdev)
- return;
+ return -ENOMEM;
dss_copy_device_pdata(dssdev, plat_dssdev);
@@ -998,7 +998,7 @@
if (r) {
DSSERR("device %s init failed: %d\n", dssdev->name, r);
dss_put_device(dssdev);
- return;
+ return r;
}
r = omapdss_output_set_device(&rfbi.output, dssdev);
@@ -1006,7 +1006,7 @@
DSSERR("failed to connect output to new device: %s\n",
dssdev->name);
dss_put_device(dssdev);
- return;
+ return r;
}
r = dss_add_device(dssdev);
@@ -1014,11 +1014,13 @@
DSSERR("device %s register failed: %d\n", dssdev->name, r);
omapdss_output_unset_device(&rfbi.output);
dss_put_device(dssdev);
- return;
+ return r;
}
+
+ return 0;
}
-static void __init rfbi_init_output(struct platform_device *pdev)
+static void rfbi_init_output(struct platform_device *pdev)
{
struct omap_dss_output *out = &rfbi.output;
@@ -1039,7 +1041,7 @@
}
/* RFBI HW IP initialisation */
-static int __init omap_rfbihw_probe(struct platform_device *pdev)
+static int omap_rfbihw_probe(struct platform_device *pdev)
{
u32 rev;
struct resource *rfbi_mem;
@@ -1091,7 +1093,12 @@
rfbi_init_output(pdev);
- rfbi_probe_pdata(pdev);
+ r = rfbi_probe_pdata(pdev);
+ if (r) {
+ rfbi_uninit_output(pdev);
+ pm_runtime_disable(&pdev->dev);
+ return r;
+ }
return 0;
@@ -1135,6 +1142,7 @@
};
static struct platform_driver omap_rfbihw_driver = {
+ .probe = omap_rfbihw_probe,
.remove = __exit_p(omap_rfbihw_remove),
.driver = {
.name = "omapdss_rfbi",
@@ -1145,7 +1153,7 @@
int __init rfbi_init_platform_driver(void)
{
- return platform_driver_probe(&omap_rfbihw_driver, omap_rfbihw_probe);
+ return platform_driver_register(&omap_rfbihw_driver);
}
void __exit rfbi_uninit_platform_driver(void)
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index e6baee2..0bcd302 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -248,7 +248,7 @@
}
EXPORT_SYMBOL(omapdss_sdi_set_datapairs);
-static int __init sdi_init_display(struct omap_dss_device *dssdev)
+static int sdi_init_display(struct omap_dss_device *dssdev)
{
DSSDBG("SDI init\n");
@@ -268,7 +268,7 @@
return 0;
}
-static struct omap_dss_device * __init sdi_find_dssdev(struct platform_device *pdev)
+static struct omap_dss_device *sdi_find_dssdev(struct platform_device *pdev)
{
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
const char *def_disp_name = omapdss_get_default_display_name();
@@ -296,7 +296,7 @@
return def_dssdev;
}
-static void __init sdi_probe_pdata(struct platform_device *sdidev)
+static int sdi_probe_pdata(struct platform_device *sdidev)
{
struct omap_dss_device *plat_dssdev;
struct omap_dss_device *dssdev;
@@ -305,11 +305,11 @@
plat_dssdev = sdi_find_dssdev(sdidev);
if (!plat_dssdev)
- return;
+ return 0;
dssdev = dss_alloc_and_init_device(&sdidev->dev);
if (!dssdev)
- return;
+ return -ENOMEM;
dss_copy_device_pdata(dssdev, plat_dssdev);
@@ -317,7 +317,7 @@
if (r) {
DSSERR("device %s init failed: %d\n", dssdev->name, r);
dss_put_device(dssdev);
- return;
+ return r;
}
r = omapdss_output_set_device(&sdi.output, dssdev);
@@ -325,7 +325,7 @@
DSSERR("failed to connect output to new device: %s\n",
dssdev->name);
dss_put_device(dssdev);
- return;
+ return r;
}
r = dss_add_device(dssdev);
@@ -333,11 +333,13 @@
DSSERR("device %s register failed: %d\n", dssdev->name, r);
omapdss_output_unset_device(&sdi.output);
dss_put_device(dssdev);
- return;
+ return r;
}
+
+ return 0;
}
-static void __init sdi_init_output(struct platform_device *pdev)
+static void sdi_init_output(struct platform_device *pdev)
{
struct omap_dss_output *out = &sdi.output;
@@ -357,11 +359,17 @@
dss_unregister_output(out);
}
-static int __init omap_sdi_probe(struct platform_device *pdev)
+static int omap_sdi_probe(struct platform_device *pdev)
{
+ int r;
+
sdi_init_output(pdev);
- sdi_probe_pdata(pdev);
+ r = sdi_probe_pdata(pdev);
+ if (r) {
+ sdi_uninit_output(pdev);
+ return r;
+ }
return 0;
}
@@ -376,6 +384,7 @@
}
static struct platform_driver omap_sdi_driver = {
+ .probe = omap_sdi_probe,
.remove = __exit_p(omap_sdi_remove),
.driver = {
.name = "omapdss_sdi",
@@ -385,7 +394,7 @@
int __init sdi_init_platform_driver(void)
{
- return platform_driver_probe(&omap_sdi_driver, omap_sdi_probe);
+ return platform_driver_register(&omap_sdi_driver);
}
void __exit sdi_uninit_platform_driver(void)
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 17764d1..74fdb3e 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -633,7 +633,7 @@
mutex_unlock(&venc.venc_lock);
}
-static int __init venc_init_display(struct omap_dss_device *dssdev)
+static int venc_init_display(struct omap_dss_device *dssdev)
{
DSSDBG("init_display\n");
@@ -726,7 +726,7 @@
return 0;
}
-static struct omap_dss_device * __init venc_find_dssdev(struct platform_device *pdev)
+static struct omap_dss_device *venc_find_dssdev(struct platform_device *pdev)
{
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
const char *def_disp_name = omapdss_get_default_display_name();
@@ -754,7 +754,7 @@
return def_dssdev;
}
-static void __init venc_probe_pdata(struct platform_device *vencdev)
+static int venc_probe_pdata(struct platform_device *vencdev)
{
struct omap_dss_device *plat_dssdev;
struct omap_dss_device *dssdev;
@@ -763,11 +763,11 @@
plat_dssdev = venc_find_dssdev(vencdev);
if (!plat_dssdev)
- return;
+ return 0;
dssdev = dss_alloc_and_init_device(&vencdev->dev);
if (!dssdev)
- return;
+ return -ENOMEM;
dss_copy_device_pdata(dssdev, plat_dssdev);
@@ -775,7 +775,7 @@
if (r) {
DSSERR("device %s init failed: %d\n", dssdev->name, r);
dss_put_device(dssdev);
- return;
+ return r;
}
r = omapdss_output_set_device(&venc.output, dssdev);
@@ -783,7 +783,7 @@
DSSERR("failed to connect output to new device: %s\n",
dssdev->name);
dss_put_device(dssdev);
- return;
+ return r;
}
r = dss_add_device(dssdev);
@@ -791,11 +791,13 @@
DSSERR("device %s register failed: %d\n", dssdev->name, r);
omapdss_output_unset_device(&venc.output);
dss_put_device(dssdev);
- return;
+ return r;
}
+
+ return 0;
}
-static void __init venc_init_output(struct platform_device *pdev)
+static void venc_init_output(struct platform_device *pdev)
{
struct omap_dss_output *out = &venc.output;
@@ -816,7 +818,7 @@
}
/* VENC HW IP initialisation */
-static int __init omap_venchw_probe(struct platform_device *pdev)
+static int omap_venchw_probe(struct platform_device *pdev)
{
u8 rev_id;
struct resource *venc_mem;
@@ -864,7 +866,13 @@
venc_init_output(pdev);
- venc_probe_pdata(pdev);
+ r = venc_probe_pdata(pdev);
+ if (r) {
+ venc_panel_exit();
+ venc_uninit_output(pdev);
+ pm_runtime_disable(&pdev->dev);
+ return r;
+ }
return 0;
@@ -922,6 +930,7 @@
};
static struct platform_driver omap_venchw_driver = {
+ .probe = omap_venchw_probe,
.remove = __exit_p(omap_venchw_remove),
.driver = {
.name = "omapdss_venc",
@@ -932,7 +941,7 @@
int __init venc_init_platform_driver(void)
{
- return platform_driver_probe(&omap_venchw_driver, omap_venchw_probe);
+ return platform_driver_register(&omap_venchw_driver);
}
void __exit venc_uninit_platform_driver(void)
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index f38348e..ff00d1d 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -2422,7 +2422,7 @@
return 0;
}
-static int __init omapfb_probe(struct platform_device *pdev)
+static int omapfb_probe(struct platform_device *pdev)
{
struct omapfb2_device *fbdev = NULL;
int r = 0;
@@ -2484,7 +2484,7 @@
if (fbdev->num_displays == 0) {
dev_err(&pdev->dev, "no displays\n");
- r = -EINVAL;
+ r = -EPROBE_DEFER;
goto cleanup;
}
@@ -2595,6 +2595,7 @@
}
static struct platform_driver omapfb_driver = {
+ .probe = omapfb_probe,
.remove = __exit_p(omapfb_remove),
.driver = {
.name = "omapfb",
@@ -2602,36 +2603,13 @@
},
};
-static int __init omapfb_init(void)
-{
- DBG("omapfb_init\n");
-
- if (platform_driver_probe(&omapfb_driver, omapfb_probe)) {
- printk(KERN_ERR "failed to register omapfb driver\n");
- return -ENODEV;
- }
-
- return 0;
-}
-
-static void __exit omapfb_exit(void)
-{
- DBG("omapfb_exit\n");
- platform_driver_unregister(&omapfb_driver);
-}
-
module_param_named(mode, def_mode, charp, 0);
module_param_named(vram, def_vram, charp, 0);
module_param_named(rotate, def_rotate, int, 0);
module_param_named(vrfb, def_vrfb, bool, 0);
module_param_named(mirror, def_mirror, bool, 0);
-/* late_initcall to let panel/ctrl drivers loaded first.
- * I guess better option would be a more dynamic approach,
- * so that omapfb reacts to new panels when they are loaded */
-late_initcall(omapfb_init);
-/*module_init(omapfb_init);*/
-module_exit(omapfb_exit);
+module_platform_driver(omapfb_driver);
MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
MODULE_DESCRIPTION("OMAP2/3 Framebuffer");
diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h
index 918e8fe..c2af598 100644
--- a/include/drm/drm_pciids.h
+++ b/include/drm/drm_pciids.h
@@ -240,6 +240,7 @@
{0x1002, 0x6819, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6821, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x6822, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6823, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6824, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
@@ -247,11 +248,13 @@
{0x1002, 0x6827, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6829, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x682A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x682B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x682D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x682F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6830, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6831, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x6835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6837, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6838, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6839, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \
@@ -603,6 +606,8 @@
{0x1002, 0x9999, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
{0x1002, 0x999A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
{0x1002, 0x999B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+ {0x1002, 0x999C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+ {0x1002, 0x999D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
{0x1002, 0x99A0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
{0x1002, 0x99A2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
{0x1002, 0x99A4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \