drm fixes for 6.19-rc1
plane: - Handle IS_ERR vs NULL in drm_plane_create_hotspot_properties(). ttm: - fix devcoredump for evicted bos panel: - Fix stack usage warning in novatek-nt35560. nouveau: - alloc fwsec sb at boot to avoid s/r problems - fix strcpy usage - fix i2c encoder crash bridge: - Ignore spurious PLL_UNLOCK bit in ti-sn65dsi83. mgag200: - Fix bigendian handling in mgag200. tilcdc: - Fix probe failure in tilcdc. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEEKbZHaGwW9KfbeusDHTzWXnEhr4FAmk8zQYACgkQDHTzWXnE hr5dsw/+Mp4jXl4VbQv6VA9ykpjuwepJHZXh8qcHAUNaku0qPa5j3PRK3qHbHKGA 2sVROdEcJUIgDbkwxOEe4V9ygn+w6qC0vLM6JYQgulUc9Haz4Srcg9g0nyagcSPD vmJdEGQzeYOXG2onkYssHJxGh1u0bfES4PY+ps/zbl+DD6he9ZxiIipr9+9SI+B/ gwbSny9OFM6gwBvvO8u8R2S7Jnad5Fa+WKniNDLgpjJ8FlcAJWcSK62vsoQKUpfk 1pbFq0SoM06YDElKVPX3O68ZYj4JvOqoK52BMs+5H+DPweqTmXZGU4q66NmKj4RA 0RRh4zTPwMSSuqy0Q2HNaccCL6E/kgvRxCbGqfm5MWu9zsicD1cC2pEFs7umAjGE 5s5QZxyG3jHQDThAXBS/gFIQaGp4fPZsCEtRWW07I19y4lVztokBYjapeh8KetEL 5kSACpHPPLsoqIwFwPyYKOz9bJQuKpQEQNQLUn3QaP6/AX5E32ogSH5vxtOgmJDQ 2VfcZ4w7ol/s4m/mlWhyANElOwH6gDIZklyHHVrwyPzg10oau8owxaFFbEcmzVh4 OU+JGfu5q84P9GP8aXuixr5/yK/346/37CHxwGxCoy6sLzNUXCDbw/OeIcOF6/qP JkyiTq84UqA6OS1M3Bku2s51CbFTuO+M/Hj9a8MQFZ01EIjr29Y= =B5M8 -----END PGP SIGNATURE----- Merge tag 'drm-fixes-2025-12-13' of https://gitlab.freedesktop.org/drm/kernel Pull more drm fixes from Dave Airlie: "These are the enqueued fixes that ended up in our fixes branch, nouveau mostly, along with some small fixes in other places. plane: - Handle IS_ERR vs NULL in drm_plane_create_hotspot_properties() ttm: - fix devcoredump for evicted bos panel: - Fix stack usage warning in novatek-nt35560 nouveau: - alloc fwsec sb at boot to avoid s/r problems - fix strcpy usage - fix i2c encoder crash bridge: - Ignore spurious PLL_UNLOCK bit in ti-sn65dsi83 mgag200: - Fix bigendian handling in mgag200 tilcdc: - Fix probe failure in tilcdc" * tag 'drm-fixes-2025-12-13' of https://gitlab.freedesktop.org/drm/kernel: drm/mgag200: Fix big-endian support drm/tilcdc: Fix removal actions in case of failed probe drm/ttm: Avoid NULL pointer deref for evicted BOs drm: nouveau: Replace sprintf() with sysfs_emit() drm/nouveau: fix circular dep oops from vendored i2c encoder drm/nouveau: refactor deprecated strcpy drm/plane: Fix IS_ERR() vs NULL check in drm_plane_create_hotspot_properties() drm/bridge: ti-sn65dsi83: ignore PLL_UNLOCK errors drm/nouveau/gsp: Allocate fwsec-sb at boot drm/panel: novatek-nt35560: avoid on-stack device structuremaster
commit
a859eca0e4
|
|
@ -429,7 +429,14 @@ static void sn65dsi83_handle_errors(struct sn65dsi83 *ctx)
|
|||
*/
|
||||
|
||||
ret = regmap_read(ctx->regmap, REG_IRQ_STAT, &irq_stat);
|
||||
if (ret || irq_stat) {
|
||||
|
||||
/*
|
||||
* Some hardware (Toradex Verdin AM62) is known to report the
|
||||
* PLL_UNLOCK error interrupt while working without visible
|
||||
* problems. In lack of a reliable way to discriminate such cases
|
||||
* from user-visible PLL_UNLOCK cases, ignore that bit entirely.
|
||||
*/
|
||||
if (ret || irq_stat & ~REG_IRQ_STAT_CHA_PLL_UNLOCK) {
|
||||
/*
|
||||
* IRQ acknowledged is not always possible (the bridge can be in
|
||||
* a state where it doesn't answer anymore). To prevent an
|
||||
|
|
@ -654,7 +661,7 @@ static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
|
|||
if (ctx->irq) {
|
||||
/* Enable irq to detect errors */
|
||||
regmap_write(ctx->regmap, REG_IRQ_GLOBAL, REG_IRQ_GLOBAL_IRQ_EN);
|
||||
regmap_write(ctx->regmap, REG_IRQ_EN, 0xff);
|
||||
regmap_write(ctx->regmap, REG_IRQ_EN, 0xff & ~REG_IRQ_EN_CHA_PLL_UNLOCK_EN);
|
||||
} else {
|
||||
/* Use the polling task */
|
||||
sn65dsi83_monitor_start(ctx);
|
||||
|
|
|
|||
|
|
@ -338,14 +338,14 @@ static int drm_plane_create_hotspot_properties(struct drm_plane *plane)
|
|||
|
||||
prop_x = drm_property_create_signed_range(plane->dev, 0, "HOTSPOT_X",
|
||||
INT_MIN, INT_MAX);
|
||||
if (IS_ERR(prop_x))
|
||||
return PTR_ERR(prop_x);
|
||||
if (!prop_x)
|
||||
return -ENOMEM;
|
||||
|
||||
prop_y = drm_property_create_signed_range(plane->dev, 0, "HOTSPOT_Y",
|
||||
INT_MIN, INT_MAX);
|
||||
if (IS_ERR(prop_y)) {
|
||||
if (!prop_y) {
|
||||
drm_property_destroy(plane->dev, prop_x);
|
||||
return PTR_ERR(prop_y);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
drm_object_attach_property(&plane->base, prop_x, 0);
|
||||
|
|
|
|||
|
|
@ -161,6 +161,30 @@ static void mgag200_set_startadd(struct mga_device *mdev,
|
|||
WREG_ECRT(0x00, crtcext0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the opmode for the hardware swapper for Big-Endian processor
|
||||
* support for the frame buffer aperture and DMAWIN space.
|
||||
*/
|
||||
static void mgag200_set_datasiz(struct mga_device *mdev, u32 format)
|
||||
{
|
||||
#if defined(__BIG_ENDIAN)
|
||||
u32 opmode = RREG32(MGAREG_OPMODE);
|
||||
|
||||
opmode &= ~(GENMASK(17, 16) | GENMASK(9, 8) | GENMASK(3, 2));
|
||||
|
||||
/* Big-endian byte-swapping */
|
||||
switch (format) {
|
||||
case DRM_FORMAT_RGB565:
|
||||
opmode |= 0x10100;
|
||||
break;
|
||||
case DRM_FORMAT_XRGB8888:
|
||||
opmode |= 0x20200;
|
||||
break;
|
||||
}
|
||||
WREG32(MGAREG_OPMODE, opmode);
|
||||
#endif
|
||||
}
|
||||
|
||||
void mgag200_init_registers(struct mga_device *mdev)
|
||||
{
|
||||
u8 crtc11, misc;
|
||||
|
|
@ -496,6 +520,7 @@ void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane,
|
|||
struct drm_atomic_helper_damage_iter iter;
|
||||
struct drm_rect damage;
|
||||
|
||||
mgag200_set_datasiz(mdev, fb->format->format);
|
||||
drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
|
||||
drm_atomic_for_each_plane_damage(&iter, &damage) {
|
||||
mgag200_handle_damage(mdev, shadow_plane_state->data, fb, &damage);
|
||||
|
|
|
|||
|
|
@ -94,26 +94,6 @@ fail_unregister:
|
|||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* nouveau_i2c_encoder_destroy - Unregister the I2C device backing an encoder
|
||||
* @drm_encoder: Encoder to be unregistered.
|
||||
*
|
||||
* This should be called from the @destroy method of an I2C slave
|
||||
* encoder driver once I2C access is no longer needed.
|
||||
*/
|
||||
void nouveau_i2c_encoder_destroy(struct drm_encoder *drm_encoder)
|
||||
{
|
||||
struct nouveau_i2c_encoder *encoder = to_encoder_i2c(drm_encoder);
|
||||
struct i2c_client *client = nouveau_i2c_encoder_get_client(drm_encoder);
|
||||
struct module *module = client->dev.driver->owner;
|
||||
|
||||
i2c_unregister_device(client);
|
||||
encoder->i2c_client = NULL;
|
||||
|
||||
module_put(module);
|
||||
}
|
||||
EXPORT_SYMBOL(nouveau_i2c_encoder_destroy);
|
||||
|
||||
/*
|
||||
* Wrapper fxns which can be plugged in to drm_encoder_helper_funcs:
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -202,7 +202,24 @@ static inline struct i2c_client *nouveau_i2c_encoder_get_client(struct drm_encod
|
|||
return to_encoder_i2c(encoder)->i2c_client;
|
||||
}
|
||||
|
||||
void nouveau_i2c_encoder_destroy(struct drm_encoder *encoder);
|
||||
/**
|
||||
* nouveau_i2c_encoder_destroy - Unregister the I2C device backing an encoder
|
||||
* @drm_encoder: Encoder to be unregistered.
|
||||
*
|
||||
* This should be called from the @destroy method of an I2C slave
|
||||
* encoder driver once I2C access is no longer needed.
|
||||
*/
|
||||
static __always_inline void nouveau_i2c_encoder_destroy(struct drm_encoder *drm_encoder)
|
||||
{
|
||||
struct nouveau_i2c_encoder *encoder = to_encoder_i2c(drm_encoder);
|
||||
struct i2c_client *client = nouveau_i2c_encoder_get_client(drm_encoder);
|
||||
struct module *module = client->dev.driver->owner;
|
||||
|
||||
i2c_unregister_device(client);
|
||||
encoder->i2c_client = NULL;
|
||||
|
||||
module_put(module);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrapper fxns which can be plugged in to drm_encoder_helper_funcs:
|
||||
|
|
|
|||
|
|
@ -73,6 +73,10 @@ struct nvkm_gsp {
|
|||
|
||||
const struct firmware *bl;
|
||||
const struct firmware *rm;
|
||||
|
||||
struct {
|
||||
struct nvkm_falcon_fw sb;
|
||||
} falcon;
|
||||
} fws;
|
||||
|
||||
struct nvkm_firmware fw;
|
||||
|
|
|
|||
|
|
@ -183,11 +183,11 @@ nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_cha
|
|||
fctx->context = drm->runl[chan->runlist].context_base + chan->chid;
|
||||
|
||||
if (chan == drm->cechan)
|
||||
strcpy(fctx->name, "copy engine channel");
|
||||
strscpy(fctx->name, "copy engine channel");
|
||||
else if (chan == drm->channel)
|
||||
strcpy(fctx->name, "generic kernel channel");
|
||||
strscpy(fctx->name, "generic kernel channel");
|
||||
else
|
||||
strcpy(fctx->name, cli->name);
|
||||
strscpy(fctx->name, cli->name);
|
||||
|
||||
kref_init(&fctx->fence_ref);
|
||||
if (!priv->uevent)
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ nouveau_hwmon_get_pwm1_max(struct device *d,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return sprintf(buf, "%i\n", ret);
|
||||
return sysfs_emit(buf, "%i\n", ret);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
|
|
@ -141,7 +141,7 @@ nouveau_hwmon_get_pwm1_min(struct device *d,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return sprintf(buf, "%i\n", ret);
|
||||
return sysfs_emit(buf, "%i\n", ret);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
|
|
|
|||
|
|
@ -259,18 +259,16 @@ nvkm_gsp_fwsec_v3(struct nvkm_gsp *gsp, const char *name,
|
|||
}
|
||||
|
||||
static int
|
||||
nvkm_gsp_fwsec(struct nvkm_gsp *gsp, const char *name, u32 init_cmd)
|
||||
nvkm_gsp_fwsec_init(struct nvkm_gsp *gsp, struct nvkm_falcon_fw *fw, const char *name, u32 init_cmd)
|
||||
{
|
||||
struct nvkm_subdev *subdev = &gsp->subdev;
|
||||
struct nvkm_device *device = subdev->device;
|
||||
struct nvkm_bios *bios = device->bios;
|
||||
const union nvfw_falcon_ucode_desc *desc;
|
||||
struct nvbios_pmuE flcn_ucode;
|
||||
u8 idx, ver, hdr;
|
||||
u32 data;
|
||||
u16 size, vers;
|
||||
struct nvkm_falcon_fw fw = {};
|
||||
u32 mbox0 = 0;
|
||||
u8 idx, ver, hdr;
|
||||
int ret;
|
||||
|
||||
/* Lookup in VBIOS. */
|
||||
|
|
@ -291,8 +289,8 @@ nvkm_gsp_fwsec(struct nvkm_gsp *gsp, const char *name, u32 init_cmd)
|
|||
vers = (desc->v2.Hdr & 0x0000ff00) >> 8;
|
||||
|
||||
switch (vers) {
|
||||
case 2: ret = nvkm_gsp_fwsec_v2(gsp, name, &desc->v2, size, init_cmd, &fw); break;
|
||||
case 3: ret = nvkm_gsp_fwsec_v3(gsp, name, &desc->v3, size, init_cmd, &fw); break;
|
||||
case 2: ret = nvkm_gsp_fwsec_v2(gsp, name, &desc->v2, size, init_cmd, fw); break;
|
||||
case 3: ret = nvkm_gsp_fwsec_v3(gsp, name, &desc->v3, size, init_cmd, fw); break;
|
||||
default:
|
||||
nvkm_error(subdev, "%s(v%d): version unknown\n", name, vers);
|
||||
return -EINVAL;
|
||||
|
|
@ -303,15 +301,19 @@ nvkm_gsp_fwsec(struct nvkm_gsp *gsp, const char *name, u32 init_cmd)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Boot. */
|
||||
ret = nvkm_falcon_fw_boot(&fw, subdev, true, &mbox0, NULL, 0, 0);
|
||||
nvkm_falcon_fw_dtor(&fw);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nvkm_gsp_fwsec_boot(struct nvkm_gsp *gsp, struct nvkm_falcon_fw *fw)
|
||||
{
|
||||
struct nvkm_subdev *subdev = &gsp->subdev;
|
||||
u32 mbox0 = 0;
|
||||
|
||||
/* Boot */
|
||||
return nvkm_falcon_fw_boot(fw, subdev, true, &mbox0, NULL, 0, 0);
|
||||
}
|
||||
|
||||
int
|
||||
nvkm_gsp_fwsec_sb(struct nvkm_gsp *gsp)
|
||||
{
|
||||
|
|
@ -320,7 +322,7 @@ nvkm_gsp_fwsec_sb(struct nvkm_gsp *gsp)
|
|||
int ret;
|
||||
u32 err;
|
||||
|
||||
ret = nvkm_gsp_fwsec(gsp, "fwsec-sb", NVFW_FALCON_APPIF_DMEMMAPPER_CMD_SB);
|
||||
ret = nvkm_gsp_fwsec_boot(gsp, &gsp->fws.falcon.sb);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -334,27 +336,48 @@ nvkm_gsp_fwsec_sb(struct nvkm_gsp *gsp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nvkm_gsp_fwsec_sb_ctor(struct nvkm_gsp *gsp)
|
||||
{
|
||||
return nvkm_gsp_fwsec_init(gsp, &gsp->fws.falcon.sb, "fwsec-sb",
|
||||
NVFW_FALCON_APPIF_DMEMMAPPER_CMD_SB);
|
||||
}
|
||||
|
||||
void
|
||||
nvkm_gsp_fwsec_sb_dtor(struct nvkm_gsp *gsp)
|
||||
{
|
||||
nvkm_falcon_fw_dtor(&gsp->fws.falcon.sb);
|
||||
}
|
||||
|
||||
int
|
||||
nvkm_gsp_fwsec_frts(struct nvkm_gsp *gsp)
|
||||
{
|
||||
struct nvkm_subdev *subdev = &gsp->subdev;
|
||||
struct nvkm_device *device = subdev->device;
|
||||
struct nvkm_falcon_fw fw = {};
|
||||
int ret;
|
||||
u32 err, wpr2_lo, wpr2_hi;
|
||||
|
||||
ret = nvkm_gsp_fwsec(gsp, "fwsec-frts", NVFW_FALCON_APPIF_DMEMMAPPER_CMD_FRTS);
|
||||
ret = nvkm_gsp_fwsec_init(gsp, &fw, "fwsec-frts", NVFW_FALCON_APPIF_DMEMMAPPER_CMD_FRTS);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = nvkm_gsp_fwsec_boot(gsp, &fw);
|
||||
if (ret)
|
||||
goto fwsec_dtor;
|
||||
|
||||
/* Verify. */
|
||||
err = nvkm_rd32(device, 0x001400 + (0xe * 4)) >> 16;
|
||||
if (err) {
|
||||
nvkm_error(subdev, "fwsec-frts: 0x%04x\n", err);
|
||||
return -EIO;
|
||||
ret = -EIO;
|
||||
} else {
|
||||
wpr2_lo = nvkm_rd32(device, 0x1fa824);
|
||||
wpr2_hi = nvkm_rd32(device, 0x1fa828);
|
||||
nvkm_debug(subdev, "fwsec-frts: WPR2 @ %08x - %08x\n", wpr2_lo, wpr2_hi);
|
||||
}
|
||||
|
||||
wpr2_lo = nvkm_rd32(device, 0x1fa824);
|
||||
wpr2_hi = nvkm_rd32(device, 0x1fa828);
|
||||
nvkm_debug(subdev, "fwsec-frts: WPR2 @ %08x - %08x\n", wpr2_lo, wpr2_hi);
|
||||
return 0;
|
||||
fwsec_dtor:
|
||||
nvkm_falcon_fw_dtor(&fw);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,10 @@
|
|||
enum nvkm_acr_lsf_id;
|
||||
|
||||
int nvkm_gsp_fwsec_frts(struct nvkm_gsp *);
|
||||
|
||||
int nvkm_gsp_fwsec_sb_ctor(struct nvkm_gsp *);
|
||||
int nvkm_gsp_fwsec_sb(struct nvkm_gsp *);
|
||||
void nvkm_gsp_fwsec_sb_dtor(struct nvkm_gsp *);
|
||||
|
||||
struct nvkm_gsp_fwif {
|
||||
int version;
|
||||
|
|
|
|||
|
|
@ -1817,12 +1817,16 @@ r535_gsp_rm_boot_ctor(struct nvkm_gsp *gsp)
|
|||
RM_RISCV_UCODE_DESC *desc;
|
||||
int ret;
|
||||
|
||||
ret = nvkm_gsp_fwsec_sb_ctor(gsp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
hdr = nvfw_bin_hdr(&gsp->subdev, fw->data);
|
||||
desc = (void *)fw->data + hdr->header_offset;
|
||||
|
||||
ret = nvkm_gsp_mem_ctor(gsp, hdr->data_size, &gsp->boot.fw);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto dtor_fwsec;
|
||||
|
||||
memcpy(gsp->boot.fw.data, fw->data + hdr->data_offset, hdr->data_size);
|
||||
|
||||
|
|
@ -1831,6 +1835,9 @@ r535_gsp_rm_boot_ctor(struct nvkm_gsp *gsp)
|
|||
gsp->boot.manifest_offset = desc->manifestOffset;
|
||||
gsp->boot.app_version = desc->appVersion;
|
||||
return 0;
|
||||
dtor_fwsec:
|
||||
nvkm_gsp_fwsec_sb_dtor(gsp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct nvkm_firmware_func
|
||||
|
|
@ -2101,6 +2108,7 @@ r535_gsp_dtor(struct nvkm_gsp *gsp)
|
|||
mutex_destroy(&gsp->cmdq.mutex);
|
||||
|
||||
nvkm_gsp_dtor_fws(gsp);
|
||||
nvkm_gsp_fwsec_sb_dtor(gsp);
|
||||
|
||||
nvkm_gsp_mem_dtor(&gsp->rmargs);
|
||||
nvkm_gsp_mem_dtor(&gsp->wpr_meta);
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ static const struct backlight_properties nt35560_bl_props = {
|
|||
|
||||
static void nt35560_read_id(struct mipi_dsi_multi_context *dsi_ctx)
|
||||
{
|
||||
struct device dev = dsi_ctx->dsi->dev;
|
||||
struct device *dev = &dsi_ctx->dsi->dev;
|
||||
u8 vendor, version, panel;
|
||||
u16 val;
|
||||
|
||||
|
|
@ -225,7 +225,7 @@ static void nt35560_read_id(struct mipi_dsi_multi_context *dsi_ctx)
|
|||
return;
|
||||
|
||||
if (vendor == 0x00) {
|
||||
dev_err(&dev, "device vendor ID is zero\n");
|
||||
dev_err(dev, "device vendor ID is zero\n");
|
||||
dsi_ctx->accum_err = -ENODEV;
|
||||
return;
|
||||
}
|
||||
|
|
@ -236,12 +236,12 @@ static void nt35560_read_id(struct mipi_dsi_multi_context *dsi_ctx)
|
|||
case DISPLAY_SONY_ACX424AKP_ID2:
|
||||
case DISPLAY_SONY_ACX424AKP_ID3:
|
||||
case DISPLAY_SONY_ACX424AKP_ID4:
|
||||
dev_info(&dev,
|
||||
dev_info(dev,
|
||||
"MTP vendor: %02x, version: %02x, panel: %02x\n",
|
||||
vendor, version, panel);
|
||||
break;
|
||||
default:
|
||||
dev_info(&dev,
|
||||
dev_info(dev,
|
||||
"unknown vendor: %02x, version: %02x, panel: %02x\n",
|
||||
vendor, version, panel);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -586,7 +586,7 @@ out:
|
|||
drm_modeset_unlock(&crtc->mutex);
|
||||
}
|
||||
|
||||
static void tilcdc_crtc_destroy(struct drm_crtc *crtc)
|
||||
void tilcdc_crtc_destroy(struct drm_crtc *crtc)
|
||||
{
|
||||
struct tilcdc_drm_private *priv = crtc->dev->dev_private;
|
||||
|
||||
|
|
|
|||
|
|
@ -172,8 +172,7 @@ static void tilcdc_fini(struct drm_device *dev)
|
|||
if (priv->crtc)
|
||||
tilcdc_crtc_shutdown(priv->crtc);
|
||||
|
||||
if (priv->is_registered)
|
||||
drm_dev_unregister(dev);
|
||||
drm_dev_unregister(dev);
|
||||
|
||||
drm_kms_helper_poll_fini(dev);
|
||||
drm_atomic_helper_shutdown(dev);
|
||||
|
|
@ -220,21 +219,21 @@ static int tilcdc_init(const struct drm_driver *ddrv, struct device *dev)
|
|||
priv->wq = alloc_ordered_workqueue("tilcdc", 0);
|
||||
if (!priv->wq) {
|
||||
ret = -ENOMEM;
|
||||
goto init_failed;
|
||||
goto put_drm;
|
||||
}
|
||||
|
||||
priv->mmio = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(priv->mmio)) {
|
||||
dev_err(dev, "failed to request / ioremap\n");
|
||||
ret = PTR_ERR(priv->mmio);
|
||||
goto init_failed;
|
||||
goto free_wq;
|
||||
}
|
||||
|
||||
priv->clk = clk_get(dev, "fck");
|
||||
if (IS_ERR(priv->clk)) {
|
||||
dev_err(dev, "failed to get functional clock\n");
|
||||
ret = -ENODEV;
|
||||
goto init_failed;
|
||||
goto free_wq;
|
||||
}
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
|
|
@ -313,7 +312,7 @@ static int tilcdc_init(const struct drm_driver *ddrv, struct device *dev)
|
|||
ret = tilcdc_crtc_create(ddev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to create crtc\n");
|
||||
goto init_failed;
|
||||
goto disable_pm;
|
||||
}
|
||||
modeset_init(ddev);
|
||||
|
||||
|
|
@ -324,46 +323,46 @@ static int tilcdc_init(const struct drm_driver *ddrv, struct device *dev)
|
|||
if (ret) {
|
||||
dev_err(dev, "failed to register cpufreq notifier\n");
|
||||
priv->freq_transition.notifier_call = NULL;
|
||||
goto init_failed;
|
||||
goto destroy_crtc;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (priv->is_componentized) {
|
||||
ret = component_bind_all(dev, ddev);
|
||||
if (ret < 0)
|
||||
goto init_failed;
|
||||
goto unregister_cpufreq_notif;
|
||||
|
||||
ret = tilcdc_add_component_encoder(ddev);
|
||||
if (ret < 0)
|
||||
goto init_failed;
|
||||
goto unbind_component;
|
||||
} else {
|
||||
ret = tilcdc_attach_external_device(ddev);
|
||||
if (ret)
|
||||
goto init_failed;
|
||||
goto unregister_cpufreq_notif;
|
||||
}
|
||||
|
||||
if (!priv->external_connector &&
|
||||
((priv->num_encoders == 0) || (priv->num_connectors == 0))) {
|
||||
dev_err(dev, "no encoders/connectors found\n");
|
||||
ret = -EPROBE_DEFER;
|
||||
goto init_failed;
|
||||
goto unbind_component;
|
||||
}
|
||||
|
||||
ret = drm_vblank_init(ddev, 1);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to initialize vblank\n");
|
||||
goto init_failed;
|
||||
goto unbind_component;
|
||||
}
|
||||
|
||||
ret = platform_get_irq(pdev, 0);
|
||||
if (ret < 0)
|
||||
goto init_failed;
|
||||
goto unbind_component;
|
||||
priv->irq = ret;
|
||||
|
||||
ret = tilcdc_irq_install(ddev, priv->irq);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to install IRQ handler\n");
|
||||
goto init_failed;
|
||||
goto unbind_component;
|
||||
}
|
||||
|
||||
drm_mode_config_reset(ddev);
|
||||
|
|
@ -372,16 +371,34 @@ static int tilcdc_init(const struct drm_driver *ddrv, struct device *dev)
|
|||
|
||||
ret = drm_dev_register(ddev, 0);
|
||||
if (ret)
|
||||
goto init_failed;
|
||||
priv->is_registered = true;
|
||||
goto stop_poll;
|
||||
|
||||
drm_client_setup_with_color_mode(ddev, bpp);
|
||||
|
||||
return 0;
|
||||
|
||||
init_failed:
|
||||
tilcdc_fini(ddev);
|
||||
stop_poll:
|
||||
drm_kms_helper_poll_fini(ddev);
|
||||
tilcdc_irq_uninstall(ddev);
|
||||
unbind_component:
|
||||
if (priv->is_componentized)
|
||||
component_unbind_all(dev, ddev);
|
||||
unregister_cpufreq_notif:
|
||||
#ifdef CONFIG_CPU_FREQ
|
||||
cpufreq_unregister_notifier(&priv->freq_transition,
|
||||
CPUFREQ_TRANSITION_NOTIFIER);
|
||||
destroy_crtc:
|
||||
#endif
|
||||
tilcdc_crtc_destroy(priv->crtc);
|
||||
disable_pm:
|
||||
pm_runtime_disable(dev);
|
||||
clk_put(priv->clk);
|
||||
free_wq:
|
||||
destroy_workqueue(priv->wq);
|
||||
put_drm:
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
ddev->dev_private = NULL;
|
||||
drm_dev_put(ddev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,7 +82,6 @@ struct tilcdc_drm_private {
|
|||
struct drm_encoder *external_encoder;
|
||||
struct drm_connector *external_connector;
|
||||
|
||||
bool is_registered;
|
||||
bool is_componentized;
|
||||
bool irq_enabled;
|
||||
};
|
||||
|
|
@ -164,6 +163,7 @@ void tilcdc_crtc_set_panel_info(struct drm_crtc *crtc,
|
|||
void tilcdc_crtc_set_simulate_vesa_sync(struct drm_crtc *crtc,
|
||||
bool simulate_vesa_sync);
|
||||
void tilcdc_crtc_shutdown(struct drm_crtc *crtc);
|
||||
void tilcdc_crtc_destroy(struct drm_crtc *crtc);
|
||||
int tilcdc_crtc_update_fb(struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
struct drm_pending_vblank_event *event);
|
||||
|
|
|
|||
|
|
@ -434,6 +434,11 @@ int ttm_bo_access(struct ttm_buffer_object *bo, unsigned long offset,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!bo->resource) {
|
||||
ret = -ENODATA;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
switch (bo->resource->mem_type) {
|
||||
case TTM_PL_SYSTEM:
|
||||
fallthrough;
|
||||
|
|
@ -448,6 +453,7 @@ int ttm_bo_access(struct ttm_buffer_object *bo, unsigned long offset,
|
|||
ret = -EIO;
|
||||
}
|
||||
|
||||
unlock:
|
||||
ttm_bo_unreserve(bo);
|
||||
|
||||
return ret;
|
||||
|
|
|
|||
Loading…
Reference in New Issue