Merge tag 'drm-misc-next-2023-03-23' of git://anongit.freedesktop.org/drm/drm-misc into drm-next

drm-misc-next for v6.4-rc1:

Core Changes:
- Add unit test for xrgb8888 to mono.
- Assorted small fixes to format helper selftests.
- Assorted documentation updates.
- Drop drm_dev_set_unique.
- Always use shadow buffer in generic fbdev emulation helpers, and
  improve error handling.

Driver Changes:
- Assorted small fixes to malidp, hdlcd, gma500, lima, bridge, rockchip.
- Move fbdev in gma500 to use drm_client.
- Convert bridge platform callbacks to void return.
- Drop leftover from vgem to shmem helper conversion.

Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/5a4c438e-7047-c044-fc77-5a3597000264@linux.intel.com
This commit is contained in:
Daniel Vetter 2023-03-24 19:35:37 +01:00
commit 9578a10d4a
44 changed files with 662 additions and 797 deletions

View File

@ -100,7 +100,6 @@ static int hdlcd_load(struct drm_device *drm, unsigned long flags)
{
struct hdlcd_drm_private *hdlcd = drm_to_hdlcd_priv(drm);
struct platform_device *pdev = to_platform_device(drm->dev);
struct resource *res;
u32 version;
int ret;
@ -115,8 +114,7 @@ static int hdlcd_load(struct drm_device *drm, unsigned long flags)
atomic_set(&hdlcd->dma_end_count, 0);
#endif
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
hdlcd->mmio = devm_ioremap_resource(drm->dev, res);
hdlcd->mmio = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(hdlcd->mmio)) {
DRM_ERROR("failed to map control registers area\n");
ret = PTR_ERR(hdlcd->mmio);

View File

@ -724,8 +724,7 @@ static int malidp_bind(struct device *dev)
hwdev->hw = (struct malidp_hw *)of_device_get_match_data(dev);
malidp->dev = hwdev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
hwdev->regs = devm_ioremap_resource(dev, res);
hwdev->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(hwdev->regs))
return PTR_ERR(hwdev->regs);

View File

@ -103,22 +103,19 @@ void adv7533_dsi_power_off(struct adv7511 *adv)
enum drm_mode_status adv7533_mode_valid(struct adv7511 *adv,
const struct drm_display_mode *mode)
{
int lanes;
unsigned long max_lane_freq;
struct mipi_dsi_device *dsi = adv->dsi;
u8 bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
if (mode->clock > 80000)
lanes = 4;
else
lanes = 3;
/* Check max clock for either 7533 or 7535 */
if (mode->clock > (adv->type == ADV7533 ? 80000 : 148500))
return MODE_CLOCK_HIGH;
/*
* TODO: add support for dynamic switching of lanes
* by using the bridge pre_enable() op . Till then filter
* out the modes which shall need different number of lanes
* than what was configured in the device tree.
*/
if (lanes != dsi->lanes)
return MODE_BAD;
/* Check max clock for each lane */
max_lane_freq = (adv->type == ADV7533 ? 800000 : 891000);
if (mode->clock * bpp > max_lane_freq * adv->num_dsi_lanes)
return MODE_CLOCK_HIGH;
return MODE_OK;
}

View File

@ -1278,7 +1278,7 @@ err_disable_pclk:
return ret;
}
static int cdns_dsi_drm_remove(struct platform_device *pdev)
static void cdns_dsi_drm_remove(struct platform_device *pdev)
{
struct cdns_dsi *dsi = platform_get_drvdata(pdev);
@ -1288,8 +1288,6 @@ static int cdns_dsi_drm_remove(struct platform_device *pdev)
dsi->platform_ops->deinit(dsi);
pm_runtime_disable(&pdev->dev);
return 0;
}
static const struct of_device_id cdns_dsi_of_match[] = {
@ -1303,7 +1301,7 @@ MODULE_DEVICE_TABLE(of, cdns_dsi_of_match);
static struct platform_driver cdns_dsi_platform_driver = {
.probe = cdns_dsi_drm_probe,
.remove = cdns_dsi_drm_remove,
.remove_new = cdns_dsi_drm_remove,
.driver = {
.name = "cdns-dsi",
.of_match_table = cdns_dsi_of_match,

View File

@ -271,12 +271,9 @@ static int display_connector_probe(struct platform_device *pdev)
type == DRM_MODE_CONNECTOR_DisplayPort) {
conn->hpd_gpio = devm_gpiod_get_optional(&pdev->dev, "hpd",
GPIOD_IN);
if (IS_ERR(conn->hpd_gpio)) {
if (PTR_ERR(conn->hpd_gpio) != -EPROBE_DEFER)
dev_err(&pdev->dev,
"Unable to retrieve HPD GPIO\n");
return PTR_ERR(conn->hpd_gpio);
}
if (IS_ERR(conn->hpd_gpio))
return dev_err_probe(&pdev->dev, PTR_ERR(conn->hpd_gpio),
"Unable to retrieve HPD GPIO\n");
conn->hpd_irq = gpiod_to_irq(conn->hpd_gpio);
} else {
@ -382,7 +379,7 @@ static int display_connector_probe(struct platform_device *pdev)
return 0;
}
static int display_connector_remove(struct platform_device *pdev)
static void display_connector_remove(struct platform_device *pdev)
{
struct display_connector *conn = platform_get_drvdata(pdev);
@ -396,8 +393,6 @@ static int display_connector_remove(struct platform_device *pdev)
if (!IS_ERR(conn->bridge.ddc))
i2c_put_adapter(conn->bridge.ddc);
return 0;
}
static const struct of_device_id display_connector_match[] = {
@ -426,7 +421,7 @@ MODULE_DEVICE_TABLE(of, display_connector_match);
static struct platform_driver display_connector_driver = {
.probe = display_connector_probe,
.remove = display_connector_remove,
.remove_new = display_connector_remove,
.driver = {
.name = "display-connector",
.of_match_table = display_connector_match,

View File

@ -347,13 +347,11 @@ static int fsl_ldb_probe(struct platform_device *pdev)
return 0;
}
static int fsl_ldb_remove(struct platform_device *pdev)
static void fsl_ldb_remove(struct platform_device *pdev)
{
struct fsl_ldb *fsl_ldb = platform_get_drvdata(pdev);
drm_bridge_remove(&fsl_ldb->bridge);
return 0;
}
static const struct of_device_id fsl_ldb_match[] = {
@ -367,7 +365,7 @@ MODULE_DEVICE_TABLE(of, fsl_ldb_match);
static struct platform_driver fsl_ldb_driver = {
.probe = fsl_ldb_probe,
.remove = fsl_ldb_remove,
.remove_new = fsl_ldb_remove,
.driver = {
.name = "fsl-ldb",
.of_match_table = fsl_ldb_match,

View File

@ -532,7 +532,7 @@ static int imx8qm_ldb_probe(struct platform_device *pdev)
return ret;
}
static int imx8qm_ldb_remove(struct platform_device *pdev)
static void imx8qm_ldb_remove(struct platform_device *pdev)
{
struct imx8qm_ldb *imx8qm_ldb = platform_get_drvdata(pdev);
struct ldb *ldb = &imx8qm_ldb->base;
@ -540,8 +540,6 @@ static int imx8qm_ldb_remove(struct platform_device *pdev)
ldb_remove_bridge_helper(ldb);
pm_runtime_disable(&pdev->dev);
return 0;
}
static int __maybe_unused imx8qm_ldb_runtime_suspend(struct device *dev)
@ -573,7 +571,7 @@ MODULE_DEVICE_TABLE(of, imx8qm_ldb_dt_ids);
static struct platform_driver imx8qm_ldb_driver = {
.probe = imx8qm_ldb_probe,
.remove = imx8qm_ldb_remove,
.remove_new = imx8qm_ldb_remove,
.driver = {
.pm = &imx8qm_ldb_pm_ops,
.name = DRIVER_NAME,

View File

@ -667,7 +667,7 @@ static int imx8qxp_ldb_probe(struct platform_device *pdev)
return ret;
}
static int imx8qxp_ldb_remove(struct platform_device *pdev)
static void imx8qxp_ldb_remove(struct platform_device *pdev)
{
struct imx8qxp_ldb *imx8qxp_ldb = platform_get_drvdata(pdev);
struct ldb *ldb = &imx8qxp_ldb->base;
@ -675,8 +675,6 @@ static int imx8qxp_ldb_remove(struct platform_device *pdev)
ldb_remove_bridge_helper(ldb);
pm_runtime_disable(&pdev->dev);
return 0;
}
static int __maybe_unused imx8qxp_ldb_runtime_suspend(struct device *dev)
@ -708,7 +706,7 @@ MODULE_DEVICE_TABLE(of, imx8qxp_ldb_dt_ids);
static struct platform_driver imx8qxp_ldb_driver = {
.probe = imx8qxp_ldb_probe,
.remove = imx8qxp_ldb_remove,
.remove_new = imx8qxp_ldb_remove,
.driver = {
.pm = &imx8qxp_ldb_pm_ops,
.name = DRIVER_NAME,

View File

@ -357,7 +357,7 @@ free_child:
return ret;
}
static int imx8qxp_pc_bridge_remove(struct platform_device *pdev)
static void imx8qxp_pc_bridge_remove(struct platform_device *pdev)
{
struct imx8qxp_pc *pc = platform_get_drvdata(pdev);
struct imx8qxp_pc_channel *ch;
@ -374,8 +374,6 @@ static int imx8qxp_pc_bridge_remove(struct platform_device *pdev)
}
pm_runtime_disable(&pdev->dev);
return 0;
}
static int __maybe_unused imx8qxp_pc_runtime_suspend(struct device *dev)
@ -435,7 +433,7 @@ MODULE_DEVICE_TABLE(of, imx8qxp_pc_dt_ids);
static struct platform_driver imx8qxp_pc_bridge_driver = {
.probe = imx8qxp_pc_bridge_probe,
.remove = imx8qxp_pc_bridge_remove,
.remove_new = imx8qxp_pc_bridge_remove,
.driver = {
.pm = &imx8qxp_pc_pm_ops,
.name = DRIVER_NAME,

View File

@ -398,13 +398,11 @@ static int imx8qxp_pixel_link_bridge_probe(struct platform_device *pdev)
return ret;
}
static int imx8qxp_pixel_link_bridge_remove(struct platform_device *pdev)
static void imx8qxp_pixel_link_bridge_remove(struct platform_device *pdev)
{
struct imx8qxp_pixel_link *pl = platform_get_drvdata(pdev);
drm_bridge_remove(&pl->bridge);
return 0;
}
static const struct of_device_id imx8qxp_pixel_link_dt_ids[] = {
@ -416,7 +414,7 @@ MODULE_DEVICE_TABLE(of, imx8qxp_pixel_link_dt_ids);
static struct platform_driver imx8qxp_pixel_link_bridge_driver = {
.probe = imx8qxp_pixel_link_bridge_probe,
.remove = imx8qxp_pixel_link_bridge_remove,
.remove_new = imx8qxp_pixel_link_bridge_remove,
.driver = {
.of_match_table = imx8qxp_pixel_link_dt_ids,
.name = DRIVER_NAME,

View File

@ -455,15 +455,13 @@ static int imx8qxp_pxl2dpi_bridge_probe(struct platform_device *pdev)
return ret;
}
static int imx8qxp_pxl2dpi_bridge_remove(struct platform_device *pdev)
static void imx8qxp_pxl2dpi_bridge_remove(struct platform_device *pdev)
{
struct imx8qxp_pxl2dpi *p2d = platform_get_drvdata(pdev);
drm_bridge_remove(&p2d->bridge);
pm_runtime_disable(&pdev->dev);
return 0;
}
static const struct of_device_id imx8qxp_pxl2dpi_dt_ids[] = {
@ -474,7 +472,7 @@ MODULE_DEVICE_TABLE(of, imx8qxp_pxl2dpi_dt_ids);
static struct platform_driver imx8qxp_pxl2dpi_bridge_driver = {
.probe = imx8qxp_pxl2dpi_bridge_probe,
.remove = imx8qxp_pxl2dpi_bridge_remove,
.remove_new = imx8qxp_pxl2dpi_bridge_remove,
.driver = {
.of_match_table = imx8qxp_pxl2dpi_dt_ids,
.name = DRIVER_NAME,

View File

@ -215,13 +215,11 @@ static int lvds_codec_probe(struct platform_device *pdev)
return 0;
}
static int lvds_codec_remove(struct platform_device *pdev)
static void lvds_codec_remove(struct platform_device *pdev)
{
struct lvds_codec *lvds_codec = platform_get_drvdata(pdev);
drm_bridge_remove(&lvds_codec->bridge);
return 0;
}
static const struct of_device_id lvds_codec_match[] = {
@ -243,7 +241,7 @@ MODULE_DEVICE_TABLE(of, lvds_codec_match);
static struct platform_driver lvds_codec_driver = {
.probe = lvds_codec_probe,
.remove = lvds_codec_remove,
.remove_new = lvds_codec_remove,
.driver = {
.name = "lvds-codec",
.of_match_table = lvds_codec_match,

View File

@ -1199,7 +1199,7 @@ static int nwl_dsi_probe(struct platform_device *pdev)
return 0;
}
static int nwl_dsi_remove(struct platform_device *pdev)
static void nwl_dsi_remove(struct platform_device *pdev)
{
struct nwl_dsi *dsi = platform_get_drvdata(pdev);
@ -1207,12 +1207,11 @@ static int nwl_dsi_remove(struct platform_device *pdev)
mipi_dsi_host_unregister(&dsi->dsi_host);
drm_bridge_remove(&dsi->bridge);
pm_runtime_disable(&pdev->dev);
return 0;
}
static struct platform_driver nwl_dsi_driver = {
.probe = nwl_dsi_probe,
.remove = nwl_dsi_remove,
.remove_new = nwl_dsi_remove,
.driver = {
.of_match_table = nwl_dsi_dt_ids,
.name = DRV_NAME,

View File

@ -867,11 +867,6 @@ static int sii9234_init_resources(struct sii9234 *ctx,
return 0;
}
static inline struct sii9234 *bridge_to_sii9234(struct drm_bridge *bridge)
{
return container_of(bridge, struct sii9234, bridge);
}
static enum drm_mode_status sii9234_mode_valid(struct drm_bridge *bridge,
const struct drm_display_info *info,
const struct drm_display_mode *mode)

View File

@ -202,11 +202,9 @@ static int simple_bridge_probe(struct platform_device *pdev)
sbridge->enable = devm_gpiod_get_optional(&pdev->dev, "enable",
GPIOD_OUT_LOW);
if (IS_ERR(sbridge->enable)) {
if (PTR_ERR(sbridge->enable) != -EPROBE_DEFER)
dev_err(&pdev->dev, "Unable to retrieve enable GPIO\n");
return PTR_ERR(sbridge->enable);
}
if (IS_ERR(sbridge->enable))
return dev_err_probe(&pdev->dev, PTR_ERR(sbridge->enable),
"Unable to retrieve enable GPIO\n");
/* Register the bridge. */
sbridge->bridge.funcs = &simple_bridge_bridge_funcs;
@ -218,13 +216,11 @@ static int simple_bridge_probe(struct platform_device *pdev)
return 0;
}
static int simple_bridge_remove(struct platform_device *pdev)
static void simple_bridge_remove(struct platform_device *pdev)
{
struct simple_bridge *sbridge = platform_get_drvdata(pdev);
drm_bridge_remove(&sbridge->bridge);
return 0;
}
/*
@ -301,7 +297,7 @@ MODULE_DEVICE_TABLE(of, simple_bridge_match);
static struct platform_driver simple_bridge_driver = {
.probe = simple_bridge_probe,
.remove = simple_bridge_remove,
.remove_new = simple_bridge_remove,
.driver = {
.name = "simple-bridge",
.of_match_table = simple_bridge_match,

View File

@ -584,13 +584,11 @@ err:
return ret;
}
static int snd_dw_hdmi_remove(struct platform_device *pdev)
static void snd_dw_hdmi_remove(struct platform_device *pdev)
{
struct snd_dw_hdmi *dw = platform_get_drvdata(pdev);
snd_card_free(dw->card);
return 0;
}
#if defined(CONFIG_PM_SLEEP) && defined(IS_NOT_BROKEN)
@ -625,7 +623,7 @@ static SIMPLE_DEV_PM_OPS(snd_dw_hdmi_pm, snd_dw_hdmi_suspend,
static struct platform_driver snd_dw_hdmi_driver = {
.probe = snd_dw_hdmi_probe,
.remove = snd_dw_hdmi_remove,
.remove_new = snd_dw_hdmi_remove,
.driver = {
.name = DRIVER_NAME,
.pm = PM_OPS,

View File

@ -296,19 +296,17 @@ static int dw_hdmi_cec_probe(struct platform_device *pdev)
return 0;
}
static int dw_hdmi_cec_remove(struct platform_device *pdev)
static void dw_hdmi_cec_remove(struct platform_device *pdev)
{
struct dw_hdmi_cec *cec = platform_get_drvdata(pdev);
cec_notifier_cec_adap_unregister(cec->notify, cec->adap);
cec_unregister_adapter(cec->adap);
return 0;
}
static struct platform_driver dw_hdmi_cec_driver = {
.probe = dw_hdmi_cec_probe,
.remove = dw_hdmi_cec_remove,
.remove_new = dw_hdmi_cec_remove,
.driver = {
.name = "dw-hdmi-cec",
},

View File

@ -172,18 +172,16 @@ static int snd_dw_hdmi_probe(struct platform_device *pdev)
return PTR_ERR_OR_ZERO(dw->audio_pdev);
}
static int snd_dw_hdmi_remove(struct platform_device *pdev)
static void snd_dw_hdmi_remove(struct platform_device *pdev)
{
struct snd_dw_hdmi *dw = platform_get_drvdata(pdev);
platform_device_unregister(dw->audio_pdev);
return 0;
}
static struct platform_driver snd_dw_hdmi_driver = {
.probe = snd_dw_hdmi_probe,
.remove = snd_dw_hdmi_remove,
.remove_new = snd_dw_hdmi_remove,
.driver = {
.name = DRIVER_NAME,
},

View File

@ -216,18 +216,16 @@ static int snd_dw_hdmi_probe(struct platform_device *pdev)
return 0;
}
static int snd_dw_hdmi_remove(struct platform_device *pdev)
static void snd_dw_hdmi_remove(struct platform_device *pdev)
{
struct platform_device *platform = dev_get_drvdata(&pdev->dev);
platform_device_unregister(platform);
return 0;
}
static struct platform_driver snd_dw_hdmi_driver = {
.probe = snd_dw_hdmi_probe,
.remove = snd_dw_hdmi_remove,
.remove_new = snd_dw_hdmi_remove,
.driver = {
.name = DRIVER_NAME,
},

View File

@ -230,13 +230,11 @@ static int thc63_probe(struct platform_device *pdev)
return 0;
}
static int thc63_remove(struct platform_device *pdev)
static void thc63_remove(struct platform_device *pdev)
{
struct thc63_dev *thc63 = platform_get_drvdata(pdev);
drm_bridge_remove(&thc63->bridge);
return 0;
}
static const struct of_device_id thc63_match[] = {
@ -247,7 +245,7 @@ MODULE_DEVICE_TABLE(of, thc63_match);
static struct platform_driver thc63_driver = {
.probe = thc63_probe,
.remove = thc63_remove,
.remove_new = thc63_remove,
.driver = {
.name = "thc63lvd1024",
.of_match_table = thc63_match,

View File

@ -355,11 +355,9 @@ static int tfp410_probe(struct platform_device *pdev)
return tfp410_init(&pdev->dev, false);
}
static int tfp410_remove(struct platform_device *pdev)
static void tfp410_remove(struct platform_device *pdev)
{
tfp410_fini(&pdev->dev);
return 0;
}
static const struct of_device_id tfp410_match[] = {
@ -370,7 +368,7 @@ MODULE_DEVICE_TABLE(of, tfp410_match);
static struct platform_driver tfp410_platform_driver = {
.probe = tfp410_probe,
.remove = tfp410_remove,
.remove_new = tfp410_remove,
.driver = {
.name = "tfp410-bridge",
.of_match_table = tfp410_match,

View File

@ -1452,7 +1452,7 @@ static const struct drm_prop_enum_list dp_colorspaces[] = {
*
* left margin, right margin, top margin, bottom margin:
* Add margins to the connector's viewport. This is typically used to
* mitigate underscan on TVs.
* mitigate overscan on TVs.
*
* The value is the size in pixels of the black border which will be
* added. The attached CRTC's content will be scaled to fill the whole

View File

@ -691,9 +691,11 @@ static int drm_dev_init(struct drm_device *dev,
}
}
ret = drm_dev_set_unique(dev, dev_name(parent));
if (ret)
dev->unique = drmm_kstrdup(dev, dev_name(parent), GFP_KERNEL);
if (!dev->unique) {
ret = -ENOMEM;
goto err;
}
return 0;
@ -1000,26 +1002,6 @@ void drm_dev_unregister(struct drm_device *dev)
}
EXPORT_SYMBOL(drm_dev_unregister);
/**
* drm_dev_set_unique - Set the unique name of a DRM device
* @dev: device of which to set the unique name
* @name: unique name
*
* Sets the unique name of a DRM device using the specified string. This is
* already done by drm_dev_init(), drivers should only override the default
* unique name for backwards compatibility reasons.
*
* Return: 0 on success or a negative error code on failure.
*/
int drm_dev_set_unique(struct drm_device *dev, const char *name)
{
drmm_kfree(dev, dev->unique);
dev->unique = drmm_kstrdup(dev, name, GFP_KERNEL);
return dev->unique ? 0 : -ENOMEM;
}
EXPORT_SYMBOL(drm_dev_set_unique);
/*
* DRM Core
* The DRM core module initializes all global DRM objects and makes them

View File

@ -60,16 +60,17 @@ MODULE_PARM_DESC(drm_fbdev_overalloc,
* In order to keep user-space compatibility, we want in certain use-cases
* to keep leaking the fbdev physical address to the user-space program
* handling the fbdev buffer.
* This is a bad habit essentially kept into closed source opengl driver
* that should really be moved into open-source upstream projects instead
* of using legacy physical addresses in user space to communicate with
* other out-of-tree kernel modules.
*
* This is a bad habit, essentially kept to support closed-source OpenGL
* drivers that should really be moved into open-source upstream projects
* instead of using legacy physical addresses in user space to communicate
* with other out-of-tree kernel modules.
*
* This module_param *should* be removed as soon as possible and be
* considered as a broken and legacy behaviour from a modern fbdev device.
*/
#if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM)
static bool drm_leak_fbdev_smem;
#if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM)
module_param_unsafe(drm_leak_fbdev_smem, bool, 0600);
MODULE_PARM_DESC(drm_leak_fbdev_smem,
"Allow unsafe leaking fbdev physical smem address [default=false]");
@ -538,6 +539,29 @@ err_release:
}
EXPORT_SYMBOL(drm_fb_helper_alloc_info);
/**
* drm_fb_helper_release_info - release fb_info and its members
* @fb_helper: driver-allocated fbdev helper
*
* A helper to release fb_info and the member cmap. Drivers do not
* need to release the allocated fb_info structure themselves, this is
* automatically done when calling drm_fb_helper_fini().
*/
void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper)
{
struct fb_info *info = fb_helper->info;
if (!info)
return;
fb_helper->info = NULL;
if (info->cmap.len)
fb_dealloc_cmap(&info->cmap);
framebuffer_release(info);
}
EXPORT_SYMBOL(drm_fb_helper_release_info);
/**
* drm_fb_helper_unregister_info - unregister fb_info framebuffer device
* @fb_helper: driver-allocated fbdev helper, can be NULL
@ -561,8 +585,6 @@ EXPORT_SYMBOL(drm_fb_helper_unregister_info);
*/
void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
{
struct fb_info *info;
if (!fb_helper)
return;
@ -574,13 +596,7 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
cancel_work_sync(&fb_helper->resume_work);
cancel_work_sync(&fb_helper->damage_work);
info = fb_helper->info;
if (info) {
if (info->cmap.len)
fb_dealloc_cmap(&info->cmap);
framebuffer_release(info);
}
fb_helper->info = NULL;
drm_fb_helper_release_info(fb_helper);
mutex_lock(&kernel_fb_helper_lock);
if (!list_empty(&fb_helper->kernel_fb_list)) {
@ -657,7 +673,7 @@ static void drm_fb_helper_memory_range_to_clip(struct fb_info *info, off_t off,
void drm_fb_helper_deferred_io(struct fb_info *info, struct list_head *pagereflist)
{
struct drm_fb_helper *helper = info->par;
unsigned long start, end, min_off, max_off;
unsigned long start, end, min_off, max_off, total_size;
struct fb_deferred_io_pageref *pageref;
struct drm_rect damage_area;
@ -675,7 +691,11 @@ void drm_fb_helper_deferred_io(struct fb_info *info, struct list_head *pagerefli
* of the screen and account for non-existing scanlines. Hence,
* keep the covered memory area within the screen buffer.
*/
max_off = min(max_off, info->screen_size);
if (info->screen_size)
total_size = info->screen_size;
else
total_size = info->fix.smem_len;
max_off = min(max_off, total_size);
if (min_off < max_off) {
drm_fb_helper_memory_range_to_clip(info, min_off, max_off - min_off, &damage_area);
@ -1964,10 +1984,6 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper)
return ret;
}
#if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM)
fb_helper->hint_leak_smem_start = drm_leak_fbdev_smem;
#endif
/* push down into drivers */
ret = (*fb_helper->funcs->fb_probe)(fb_helper, &sizes);
if (ret < 0)
@ -2166,11 +2182,8 @@ __drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper)
info = fb_helper->info;
info->var.pixclock = 0;
/* Shamelessly allow physical address leaking to userspace */
#if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM)
if (!fb_helper->hint_leak_smem_start)
#endif
/* don't leak any physical addresses to userspace */
if (!drm_leak_fbdev_smem)
info->flags |= FBINFO_HIDE_SMEM_START;
/* Need to drop locks to avoid recursive deadlock in

View File

@ -136,16 +136,9 @@ static int drm_fbdev_dma_helper_fb_probe(struct drm_fb_helper *fb_helper,
info->flags |= FBINFO_READS_FAST; /* signal caching */
info->screen_size = sizes->surface_height * fb->pitches[0];
info->screen_buffer = map.vaddr;
info->fix.smem_start = page_to_phys(virt_to_page(info->screen_buffer));
info->fix.smem_len = info->screen_size;
#if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM)
/*
* Shamelessly leak the physical address to user-space.
*/
if (fb_helper->hint_leak_smem_start && !info->fix.smem_start)
info->fix.smem_start = page_to_phys(virt_to_page(info->screen_buffer));
#endif
return 0;
err_drm_client_buffer_vunmap:

View File

@ -7,22 +7,13 @@
#include <drm/drm_drv.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem.h>
#include <drm/drm_print.h>
#include <drm/drm_fbdev_generic.h>
static bool drm_fbdev_use_shadow_fb(struct drm_fb_helper *fb_helper)
{
struct drm_device *dev = fb_helper->dev;
struct drm_framebuffer *fb = fb_helper->fb;
return dev->mode_config.prefer_shadow_fbdev ||
dev->mode_config.prefer_shadow ||
fb->funcs->dirty;
}
/* @user: 1=userspace, 0=fbcon */
static int drm_fbdev_fb_open(struct fb_info *info, int user)
static int drm_fbdev_generic_fb_open(struct fb_info *info, int user)
{
struct drm_fb_helper *fb_helper = info->par;
@ -33,7 +24,7 @@ static int drm_fbdev_fb_open(struct fb_info *info, int user)
return 0;
}
static int drm_fbdev_fb_release(struct fb_info *info, int user)
static int drm_fbdev_generic_fb_release(struct fb_info *info, int user)
{
struct drm_fb_helper *fb_helper = info->par;
@ -43,133 +34,51 @@ static int drm_fbdev_fb_release(struct fb_info *info, int user)
return 0;
}
static void drm_fbdev_fb_destroy(struct fb_info *info)
static void drm_fbdev_generic_fb_destroy(struct fb_info *info)
{
struct drm_fb_helper *fb_helper = info->par;
void *shadow = NULL;
void *shadow = info->screen_buffer;
if (!fb_helper->dev)
return;
if (info->fbdefio)
fb_deferred_io_cleanup(info);
if (drm_fbdev_use_shadow_fb(fb_helper))
shadow = info->screen_buffer;
fb_deferred_io_cleanup(info);
drm_fb_helper_fini(fb_helper);
if (shadow)
vfree(shadow);
else if (fb_helper->buffer)
drm_client_buffer_vunmap(fb_helper->buffer);
vfree(shadow);
drm_client_framebuffer_delete(fb_helper->buffer);
drm_client_release(&fb_helper->client);
drm_client_release(&fb_helper->client);
drm_fb_helper_unprepare(fb_helper);
kfree(fb_helper);
}
static int drm_fbdev_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct drm_fb_helper *fb_helper = info->par;
if (drm_fbdev_use_shadow_fb(fb_helper))
return fb_deferred_io_mmap(info, vma);
else if (fb_helper->dev->driver->gem_prime_mmap)
return fb_helper->dev->driver->gem_prime_mmap(fb_helper->buffer->gem, vma);
else
return -ENODEV;
}
static bool drm_fbdev_use_iomem(struct fb_info *info)
{
struct drm_fb_helper *fb_helper = info->par;
struct drm_client_buffer *buffer = fb_helper->buffer;
return !drm_fbdev_use_shadow_fb(fb_helper) && buffer->map.is_iomem;
}
static ssize_t drm_fbdev_fb_read(struct fb_info *info, char __user *buf,
size_t count, loff_t *ppos)
{
ssize_t ret;
if (drm_fbdev_use_iomem(info))
ret = drm_fb_helper_cfb_read(info, buf, count, ppos);
else
ret = drm_fb_helper_sys_read(info, buf, count, ppos);
return ret;
}
static ssize_t drm_fbdev_fb_write(struct fb_info *info, const char __user *buf,
size_t count, loff_t *ppos)
{
ssize_t ret;
if (drm_fbdev_use_iomem(info))
ret = drm_fb_helper_cfb_write(info, buf, count, ppos);
else
ret = drm_fb_helper_sys_write(info, buf, count, ppos);
return ret;
}
static void drm_fbdev_fb_fillrect(struct fb_info *info,
const struct fb_fillrect *rect)
{
if (drm_fbdev_use_iomem(info))
drm_fb_helper_cfb_fillrect(info, rect);
else
drm_fb_helper_sys_fillrect(info, rect);
}
static void drm_fbdev_fb_copyarea(struct fb_info *info,
const struct fb_copyarea *area)
{
if (drm_fbdev_use_iomem(info))
drm_fb_helper_cfb_copyarea(info, area);
else
drm_fb_helper_sys_copyarea(info, area);
}
static void drm_fbdev_fb_imageblit(struct fb_info *info,
const struct fb_image *image)
{
if (drm_fbdev_use_iomem(info))
drm_fb_helper_cfb_imageblit(info, image);
else
drm_fb_helper_sys_imageblit(info, image);
}
static const struct fb_ops drm_fbdev_fb_ops = {
static const struct fb_ops drm_fbdev_generic_fb_ops = {
.owner = THIS_MODULE,
.fb_open = drm_fbdev_generic_fb_open,
.fb_release = drm_fbdev_generic_fb_release,
.fb_read = drm_fb_helper_sys_read,
.fb_write = drm_fb_helper_sys_write,
DRM_FB_HELPER_DEFAULT_OPS,
.fb_open = drm_fbdev_fb_open,
.fb_release = drm_fbdev_fb_release,
.fb_destroy = drm_fbdev_fb_destroy,
.fb_mmap = drm_fbdev_fb_mmap,
.fb_read = drm_fbdev_fb_read,
.fb_write = drm_fbdev_fb_write,
.fb_fillrect = drm_fbdev_fb_fillrect,
.fb_copyarea = drm_fbdev_fb_copyarea,
.fb_imageblit = drm_fbdev_fb_imageblit,
.fb_fillrect = drm_fb_helper_sys_fillrect,
.fb_copyarea = drm_fb_helper_sys_copyarea,
.fb_imageblit = drm_fb_helper_sys_imageblit,
.fb_mmap = fb_deferred_io_mmap,
.fb_destroy = drm_fbdev_generic_fb_destroy,
};
/*
* This function uses the client API to create a framebuffer backed by a dumb buffer.
*/
static int drm_fbdev_fb_probe(struct drm_fb_helper *fb_helper,
struct drm_fb_helper_surface_size *sizes)
static int drm_fbdev_generic_helper_fb_probe(struct drm_fb_helper *fb_helper,
struct drm_fb_helper_surface_size *sizes)
{
struct drm_client_dev *client = &fb_helper->client;
struct drm_device *dev = fb_helper->dev;
struct drm_client_buffer *buffer;
struct drm_framebuffer *fb;
struct fb_info *info;
size_t screen_size;
void *screen_buffer;
u32 format;
struct iosys_map map;
int ret;
drm_dbg_kms(dev, "surface width(%d), height(%d) and bpp(%d)\n",
@ -184,64 +93,56 @@ static int drm_fbdev_fb_probe(struct drm_fb_helper *fb_helper,
fb_helper->buffer = buffer;
fb_helper->fb = buffer->fb;
fb = buffer->fb;
screen_size = buffer->gem->size;
screen_buffer = vzalloc(screen_size);
if (!screen_buffer) {
ret = -ENOMEM;
goto err_drm_client_framebuffer_delete;
}
info = drm_fb_helper_alloc_info(fb_helper);
if (IS_ERR(info))
return PTR_ERR(info);
info->fbops = &drm_fbdev_fb_ops;
info->screen_size = sizes->surface_height * fb->pitches[0];
info->fix.smem_len = info->screen_size;
info->flags = FBINFO_DEFAULT;
if (IS_ERR(info)) {
ret = PTR_ERR(info);
goto err_vfree;
}
drm_fb_helper_fill_info(info, fb_helper, sizes);
if (drm_fbdev_use_shadow_fb(fb_helper)) {
info->screen_buffer = vzalloc(info->screen_size);
if (!info->screen_buffer)
return -ENOMEM;
info->flags |= FBINFO_VIRTFB | FBINFO_READS_FAST;
info->fbops = &drm_fbdev_generic_fb_ops;
info->flags = FBINFO_DEFAULT;
/* Set a default deferred I/O handler */
fb_helper->fbdefio.delay = HZ / 20;
fb_helper->fbdefio.deferred_io = drm_fb_helper_deferred_io;
/* screen */
info->flags |= FBINFO_VIRTFB | FBINFO_READS_FAST;
info->screen_buffer = screen_buffer;
info->fix.smem_start = page_to_phys(vmalloc_to_page(info->screen_buffer));
info->fix.smem_len = screen_size;
info->fbdefio = &fb_helper->fbdefio;
ret = fb_deferred_io_init(info);
if (ret)
return ret;
} else {
/* buffer is mapped for HW framebuffer */
ret = drm_client_buffer_vmap(fb_helper->buffer, &map);
if (ret)
return ret;
if (map.is_iomem) {
info->screen_base = map.vaddr_iomem;
} else {
info->screen_buffer = map.vaddr;
info->flags |= FBINFO_VIRTFB;
}
/* deferred I/O */
fb_helper->fbdefio.delay = HZ / 20;
fb_helper->fbdefio.deferred_io = drm_fb_helper_deferred_io;
/*
* Shamelessly leak the physical address to user-space. As
* page_to_phys() is undefined for I/O memory, warn in this
* case.
*/
#if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM)
if (fb_helper->hint_leak_smem_start && info->fix.smem_start == 0 &&
!drm_WARN_ON_ONCE(dev, map.is_iomem))
info->fix.smem_start =
page_to_phys(virt_to_page(info->screen_buffer));
#endif
}
info->fbdefio = &fb_helper->fbdefio;
ret = fb_deferred_io_init(info);
if (ret)
goto err_drm_fb_helper_release_info;
return 0;
err_drm_fb_helper_release_info:
drm_fb_helper_release_info(fb_helper);
err_vfree:
vfree(screen_buffer);
err_drm_client_framebuffer_delete:
fb_helper->fb = NULL;
fb_helper->buffer = NULL;
drm_client_framebuffer_delete(buffer);
return ret;
}
static void drm_fbdev_damage_blit_real(struct drm_fb_helper *fb_helper,
struct drm_clip_rect *clip,
struct iosys_map *dst)
static void drm_fbdev_generic_damage_blit_real(struct drm_fb_helper *fb_helper,
struct drm_clip_rect *clip,
struct iosys_map *dst)
{
struct drm_framebuffer *fb = fb_helper->fb;
size_t offset = clip->y1 * fb->pitches[0];
@ -278,8 +179,8 @@ static void drm_fbdev_damage_blit_real(struct drm_fb_helper *fb_helper,
}
}
static int drm_fbdev_damage_blit(struct drm_fb_helper *fb_helper,
struct drm_clip_rect *clip)
static int drm_fbdev_generic_damage_blit(struct drm_fb_helper *fb_helper,
struct drm_clip_rect *clip)
{
struct drm_client_buffer *buffer = fb_helper->buffer;
struct iosys_map map, dst;
@ -303,7 +204,7 @@ static int drm_fbdev_damage_blit(struct drm_fb_helper *fb_helper,
goto out;
dst = map;
drm_fbdev_damage_blit_real(fb_helper, clip, &dst);
drm_fbdev_generic_damage_blit_real(fb_helper, clip, &dst);
drm_client_buffer_vunmap(buffer);
@ -313,23 +214,19 @@ out:
return ret;
}
static int drm_fbdev_fb_dirty(struct drm_fb_helper *helper, struct drm_clip_rect *clip)
static int drm_fbdev_generic_helper_fb_dirty(struct drm_fb_helper *helper,
struct drm_clip_rect *clip)
{
struct drm_device *dev = helper->dev;
int ret;
if (!drm_fbdev_use_shadow_fb(helper))
return 0;
/* Call damage handlers only if necessary */
if (!(clip->x1 < clip->x2 && clip->y1 < clip->y2))
return 0;
if (helper->buffer) {
ret = drm_fbdev_damage_blit(helper, clip);
if (drm_WARN_ONCE(dev, ret, "Damage blitter failed: ret=%d\n", ret))
return ret;
}
ret = drm_fbdev_generic_damage_blit(helper, clip);
if (drm_WARN_ONCE(dev, ret, "Damage blitter failed: ret=%d\n", ret))
return ret;
if (helper->fb->funcs->dirty) {
ret = helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, clip, 1);
@ -340,12 +237,12 @@ static int drm_fbdev_fb_dirty(struct drm_fb_helper *helper, struct drm_clip_rect
return 0;
}
static const struct drm_fb_helper_funcs drm_fb_helper_generic_funcs = {
.fb_probe = drm_fbdev_fb_probe,
.fb_dirty = drm_fbdev_fb_dirty,
static const struct drm_fb_helper_funcs drm_fbdev_generic_helper_funcs = {
.fb_probe = drm_fbdev_generic_helper_fb_probe,
.fb_dirty = drm_fbdev_generic_helper_fb_dirty,
};
static void drm_fbdev_client_unregister(struct drm_client_dev *client)
static void drm_fbdev_generic_client_unregister(struct drm_client_dev *client)
{
struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
@ -358,14 +255,14 @@ static void drm_fbdev_client_unregister(struct drm_client_dev *client)
}
}
static int drm_fbdev_client_restore(struct drm_client_dev *client)
static int drm_fbdev_generic_client_restore(struct drm_client_dev *client)
{
drm_fb_helper_lastclose(client->dev);
return 0;
}
static int drm_fbdev_client_hotplug(struct drm_client_dev *client)
static int drm_fbdev_generic_client_hotplug(struct drm_client_dev *client)
{
struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
struct drm_device *dev = client->dev;
@ -394,11 +291,11 @@ err_drm_err:
return ret;
}
static const struct drm_client_funcs drm_fbdev_client_funcs = {
static const struct drm_client_funcs drm_fbdev_generic_client_funcs = {
.owner = THIS_MODULE,
.unregister = drm_fbdev_client_unregister,
.restore = drm_fbdev_client_restore,
.hotplug = drm_fbdev_client_hotplug,
.unregister = drm_fbdev_generic_client_unregister,
.restore = drm_fbdev_generic_client_restore,
.hotplug = drm_fbdev_generic_client_hotplug,
};
/**
@ -415,20 +312,16 @@ static const struct drm_client_funcs drm_fbdev_client_funcs = {
* suspend/resume need to call drm_fb_helper_set_suspend_unlocked() themselves.
* Simple drivers might use drm_mode_config_helper_suspend().
*
* Drivers that set the dirty callback on their framebuffer will get a shadow
* fbdev buffer that is blitted onto the real buffer. This is done in order to
* make deferred I/O work with all kinds of buffers. A shadow buffer can be
* requested explicitly by setting struct drm_mode_config.prefer_shadow or
* struct drm_mode_config.prefer_shadow_fbdev to true beforehand. This is
* required to use generic fbdev emulation with SHMEM helpers.
* In order to provide fixed mmap-able memory ranges, generic fbdev emulation
* uses a shadow buffer in system memory. The implementation blits the shadow
* fbdev buffer onto the real buffer in regular intervals.
*
* This function is safe to call even when there are no connectors present.
* Setup will be retried on the next hotplug event.
*
* The fbdev is destroyed by drm_dev_unregister().
*/
void drm_fbdev_generic_setup(struct drm_device *dev,
unsigned int preferred_bpp)
void drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
{
struct drm_fb_helper *fb_helper;
int ret;
@ -439,15 +332,15 @@ void drm_fbdev_generic_setup(struct drm_device *dev,
fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL);
if (!fb_helper)
return;
drm_fb_helper_prepare(dev, fb_helper, preferred_bpp, &drm_fb_helper_generic_funcs);
drm_fb_helper_prepare(dev, fb_helper, preferred_bpp, &drm_fbdev_generic_helper_funcs);
ret = drm_client_init(dev, &fb_helper->client, "fbdev", &drm_fbdev_client_funcs);
ret = drm_client_init(dev, &fb_helper->client, "fbdev", &drm_fbdev_generic_client_funcs);
if (ret) {
drm_err(dev, "Failed to register client: %d\n", ret);
goto err_drm_client_init;
}
ret = drm_fbdev_client_hotplug(&fb_helper->client);
ret = drm_fbdev_generic_client_hotplug(&fb_helper->client);
if (ret)
drm_dbg_kms(dev, "client hotplug ret=%d\n", ret);

View File

@ -285,7 +285,7 @@ EXPORT_SYMBOL(drm_gem_dmabuf_release);
/**
* drm_gem_prime_fd_to_handle - PRIME import function for GEM drivers
* @dev: dev to export the buffer from
* @dev: drm_device to import into
* @file_priv: drm file-private structure
* @prime_fd: fd id of the dma-buf which should be imported
* @handle: pointer to storage for the handle of the imported buffer object
@ -925,7 +925,7 @@ struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev,
obj = dma_buf->priv;
if (obj->dev == dev) {
/*
* Importing dmabuf exported from out own gem increases
* Importing dmabuf exported from our own gem increases
* refcount on gem itself instead of f_count of dmabuf.
*/
drm_gem_object_get(obj);

View File

@ -38,5 +38,6 @@ gma500_gfx-y += \
psb_irq.o
gma500_gfx-$(CONFIG_ACPI) += opregion.o
gma500_gfx-$(CONFIG_DRM_FBDEV_EMULATION) += fbdev.o
obj-$(CONFIG_DRM_GMA500) += gma500_gfx.o

View File

@ -0,0 +1,344 @@
// SPDX-License-Identifier: GPL-2.0-only
/**************************************************************************
* Copyright (c) 2007-2011, Intel Corporation.
* All Rights Reserved.
*
**************************************************************************/
#include <linux/pfn_t.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_framebuffer.h>
#include "gem.h"
#include "psb_drv.h"
/*
* VM area struct
*/
static vm_fault_t psb_fbdev_vm_fault(struct vm_fault *vmf)
{
struct vm_area_struct *vma = vmf->vma;
struct fb_info *info = vma->vm_private_data;
unsigned long address = vmf->address - (vmf->pgoff << PAGE_SHIFT);
unsigned long pfn = info->fix.smem_start >> PAGE_SHIFT;
vm_fault_t err = VM_FAULT_SIGBUS;
unsigned long page_num = vma_pages(vma);
unsigned long i;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
for (i = 0; i < page_num; ++i) {
err = vmf_insert_mixed(vma, address, __pfn_to_pfn_t(pfn, PFN_DEV));
if (unlikely(err & VM_FAULT_ERROR))
break;
address += PAGE_SIZE;
++pfn;
}
return err;
}
static const struct vm_operations_struct psb_fbdev_vm_ops = {
.fault = psb_fbdev_vm_fault,
};
/*
* struct fb_ops
*/
#define CMAP_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16)
static int psb_fbdev_fb_setcolreg(unsigned int regno,
unsigned int red, unsigned int green,
unsigned int blue, unsigned int transp,
struct fb_info *info)
{
struct drm_fb_helper *fb_helper = info->par;
struct drm_framebuffer *fb = fb_helper->fb;
uint32_t v;
if (!fb)
return -ENOMEM;
if (regno > 255)
return 1;
red = CMAP_TOHW(red, info->var.red.length);
blue = CMAP_TOHW(blue, info->var.blue.length);
green = CMAP_TOHW(green, info->var.green.length);
transp = CMAP_TOHW(transp, info->var.transp.length);
v = (red << info->var.red.offset) |
(green << info->var.green.offset) |
(blue << info->var.blue.offset) |
(transp << info->var.transp.offset);
if (regno < 16) {
switch (fb->format->cpp[0] * 8) {
case 16:
((uint32_t *) info->pseudo_palette)[regno] = v;
break;
case 24:
case 32:
((uint32_t *) info->pseudo_palette)[regno] = v;
break;
}
}
return 0;
}
static int psb_fbdev_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
if (vma->vm_pgoff != 0)
return -EINVAL;
if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
return -EINVAL;
/*
* If this is a GEM object then info->screen_base is the virtual
* kernel remapping of the object. FIXME: Review if this is
* suitable for our mmap work
*/
vma->vm_ops = &psb_fbdev_vm_ops;
vma->vm_private_data = info;
vm_flags_set(vma, VM_IO | VM_MIXEDMAP | VM_DONTEXPAND | VM_DONTDUMP);
return 0;
}
static void psb_fbdev_fb_destroy(struct fb_info *info)
{
struct drm_fb_helper *fb_helper = info->par;
struct drm_framebuffer *fb = fb_helper->fb;
struct drm_gem_object *obj = fb->obj[0];
drm_fb_helper_fini(fb_helper);
drm_framebuffer_unregister_private(fb);
fb->obj[0] = NULL;
drm_framebuffer_cleanup(fb);
kfree(fb);
drm_gem_object_put(obj);
drm_client_release(&fb_helper->client);
drm_fb_helper_unprepare(fb_helper);
kfree(fb_helper);
}
static const struct fb_ops psb_fbdev_fb_ops = {
.owner = THIS_MODULE,
DRM_FB_HELPER_DEFAULT_OPS,
.fb_setcolreg = psb_fbdev_fb_setcolreg,
.fb_read = drm_fb_helper_cfb_read,
.fb_write = drm_fb_helper_cfb_write,
.fb_fillrect = drm_fb_helper_cfb_fillrect,
.fb_copyarea = drm_fb_helper_cfb_copyarea,
.fb_imageblit = drm_fb_helper_cfb_imageblit,
.fb_mmap = psb_fbdev_fb_mmap,
.fb_destroy = psb_fbdev_fb_destroy,
};
/*
* struct drm_fb_helper_funcs
*/
static int psb_fbdev_fb_probe(struct drm_fb_helper *fb_helper,
struct drm_fb_helper_surface_size *sizes)
{
struct drm_device *dev = fb_helper->dev;
struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct pci_dev *pdev = to_pci_dev(dev->dev);
struct fb_info *info;
struct drm_framebuffer *fb;
struct drm_mode_fb_cmd2 mode_cmd = { };
int size;
int ret;
struct psb_gem_object *backing;
struct drm_gem_object *obj;
u32 bpp, depth;
/* No 24-bit packed mode */
if (sizes->surface_bpp == 24) {
sizes->surface_bpp = 32;
sizes->surface_depth = 24;
}
bpp = sizes->surface_bpp;
depth = sizes->surface_depth;
/*
* If the mode does not fit in 32 bit then switch to 16 bit to get
* a console on full resolution. The X mode setting server will
* allocate its own 32-bit GEM framebuffer.
*/
size = ALIGN(sizes->surface_width * DIV_ROUND_UP(bpp, 8), 64) *
sizes->surface_height;
size = ALIGN(size, PAGE_SIZE);
if (size > dev_priv->vram_stolen_size) {
sizes->surface_bpp = 16;
sizes->surface_depth = 16;
}
bpp = sizes->surface_bpp;
depth = sizes->surface_depth;
mode_cmd.width = sizes->surface_width;
mode_cmd.height = sizes->surface_height;
mode_cmd.pitches[0] = ALIGN(mode_cmd.width * DIV_ROUND_UP(bpp, 8), 64);
mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth);
size = mode_cmd.pitches[0] * mode_cmd.height;
size = ALIGN(size, PAGE_SIZE);
/* Allocate the framebuffer in the GTT with stolen page backing */
backing = psb_gem_create(dev, size, "fb", true, PAGE_SIZE);
if (IS_ERR(backing))
return PTR_ERR(backing);
obj = &backing->base;
fb = psb_framebuffer_create(dev, &mode_cmd, obj);
if (IS_ERR(fb)) {
ret = PTR_ERR(fb);
goto err_drm_gem_object_put;
}
fb_helper->fb = fb;
info = drm_fb_helper_alloc_info(fb_helper);
if (IS_ERR(info)) {
ret = PTR_ERR(info);
goto err_drm_framebuffer_unregister_private;
}
info->fbops = &psb_fbdev_fb_ops;
info->flags = FBINFO_DEFAULT;
/* Accessed stolen memory directly */
info->screen_base = dev_priv->vram_addr + backing->offset;
info->screen_size = size;
drm_fb_helper_fill_info(info, fb_helper, sizes);
info->fix.smem_start = dev_priv->stolen_base + backing->offset;
info->fix.smem_len = size;
info->fix.ywrapstep = 0;
info->fix.ypanstep = 0;
info->fix.mmio_start = pci_resource_start(pdev, 0);
info->fix.mmio_len = pci_resource_len(pdev, 0);
memset(info->screen_base, 0, info->screen_size);
/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
dev_dbg(dev->dev, "allocated %dx%d fb\n", fb->width, fb->height);
return 0;
err_drm_framebuffer_unregister_private:
drm_framebuffer_unregister_private(fb);
fb->obj[0] = NULL;
drm_framebuffer_cleanup(fb);
kfree(fb);
err_drm_gem_object_put:
drm_gem_object_put(obj);
return ret;
}
static const struct drm_fb_helper_funcs psb_fbdev_fb_helper_funcs = {
.fb_probe = psb_fbdev_fb_probe,
};
/*
* struct drm_client_funcs and setup code
*/
static void psb_fbdev_client_unregister(struct drm_client_dev *client)
{
struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
if (fb_helper->info) {
drm_fb_helper_unregister_info(fb_helper);
} else {
drm_fb_helper_unprepare(fb_helper);
drm_client_release(&fb_helper->client);
kfree(fb_helper);
}
}
static int psb_fbdev_client_restore(struct drm_client_dev *client)
{
drm_fb_helper_lastclose(client->dev);
return 0;
}
static int psb_fbdev_client_hotplug(struct drm_client_dev *client)
{
struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
struct drm_device *dev = client->dev;
int ret;
if (dev->fb_helper)
return drm_fb_helper_hotplug_event(dev->fb_helper);
ret = drm_fb_helper_init(dev, fb_helper);
if (ret)
goto err_drm_err;
if (!drm_drv_uses_atomic_modeset(dev))
drm_helper_disable_unused_functions(dev);
ret = drm_fb_helper_initial_config(fb_helper);
if (ret)
goto err_drm_fb_helper_fini;
return 0;
err_drm_fb_helper_fini:
drm_fb_helper_fini(fb_helper);
err_drm_err:
drm_err(dev, "Failed to setup gma500 fbdev emulation (ret=%d)\n", ret);
return ret;
}
static const struct drm_client_funcs psb_fbdev_client_funcs = {
.owner = THIS_MODULE,
.unregister = psb_fbdev_client_unregister,
.restore = psb_fbdev_client_restore,
.hotplug = psb_fbdev_client_hotplug,
};
void psb_fbdev_setup(struct drm_psb_private *dev_priv)
{
struct drm_device *dev = &dev_priv->dev;
struct drm_fb_helper *fb_helper;
int ret;
fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL);
if (!fb_helper)
return;
drm_fb_helper_prepare(dev, fb_helper, 32, &psb_fbdev_fb_helper_funcs);
ret = drm_client_init(dev, &fb_helper->client, "fbdev-gma500", &psb_fbdev_client_funcs);
if (ret) {
drm_err(dev, "Failed to register client: %d\n", ret);
goto err_drm_fb_helper_unprepare;
}
ret = psb_fbdev_client_hotplug(&fb_helper->client);
if (ret)
drm_dbg_kms(dev, "client hotplug ret=%d\n", ret);
drm_client_register(&fb_helper->client);
return;
err_drm_fb_helper_unprepare:
drm_fb_helper_unprepare(fb_helper);
kfree(fb_helper);
}

View File

@ -5,158 +5,18 @@
*
**************************************************************************/
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/pfn_t.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/tty.h>
#include <drm/drm.h>
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_modeset_helper.h>
#include "framebuffer.h"
#include "gem.h"
#include "psb_drv.h"
#include "psb_intel_drv.h"
#include "psb_intel_reg.h"
static const struct drm_framebuffer_funcs psb_fb_funcs = {
.destroy = drm_gem_fb_destroy,
.create_handle = drm_gem_fb_create_handle,
};
#define CMAP_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16)
static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
struct fb_info *info)
{
struct drm_fb_helper *fb_helper = info->par;
struct drm_framebuffer *fb = fb_helper->fb;
uint32_t v;
if (!fb)
return -ENOMEM;
if (regno > 255)
return 1;
red = CMAP_TOHW(red, info->var.red.length);
blue = CMAP_TOHW(blue, info->var.blue.length);
green = CMAP_TOHW(green, info->var.green.length);
transp = CMAP_TOHW(transp, info->var.transp.length);
v = (red << info->var.red.offset) |
(green << info->var.green.offset) |
(blue << info->var.blue.offset) |
(transp << info->var.transp.offset);
if (regno < 16) {
switch (fb->format->cpp[0] * 8) {
case 16:
((uint32_t *) info->pseudo_palette)[regno] = v;
break;
case 24:
case 32:
((uint32_t *) info->pseudo_palette)[regno] = v;
break;
}
}
return 0;
}
static vm_fault_t psbfb_vm_fault(struct vm_fault *vmf)
{
struct vm_area_struct *vma = vmf->vma;
struct drm_framebuffer *fb = vma->vm_private_data;
struct drm_device *dev = fb->dev;
struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct psb_gem_object *pobj = to_psb_gem_object(fb->obj[0]);
int page_num;
int i;
unsigned long address;
vm_fault_t ret = VM_FAULT_SIGBUS;
unsigned long pfn;
unsigned long phys_addr = (unsigned long)dev_priv->stolen_base + pobj->offset;
page_num = vma_pages(vma);
address = vmf->address - (vmf->pgoff << PAGE_SHIFT);
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
for (i = 0; i < page_num; i++) {
pfn = (phys_addr >> PAGE_SHIFT);
ret = vmf_insert_mixed(vma, address,
__pfn_to_pfn_t(pfn, PFN_DEV));
if (unlikely(ret & VM_FAULT_ERROR))
break;
address += PAGE_SIZE;
phys_addr += PAGE_SIZE;
}
return ret;
}
static void psbfb_vm_open(struct vm_area_struct *vma)
{
}
static void psbfb_vm_close(struct vm_area_struct *vma)
{
}
static const struct vm_operations_struct psbfb_vm_ops = {
.fault = psbfb_vm_fault,
.open = psbfb_vm_open,
.close = psbfb_vm_close
};
static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct drm_fb_helper *fb_helper = info->par;
struct drm_framebuffer *fb = fb_helper->fb;
if (vma->vm_pgoff != 0)
return -EINVAL;
if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
return -EINVAL;
/*
* If this is a GEM object then info->screen_base is the virtual
* kernel remapping of the object. FIXME: Review if this is
* suitable for our mmap work
*/
vma->vm_ops = &psbfb_vm_ops;
vma->vm_private_data = (void *)fb;
vm_flags_set(vma, VM_IO | VM_MIXEDMAP | VM_DONTEXPAND | VM_DONTDUMP);
return 0;
}
static const struct fb_ops psbfb_unaccel_ops = {
.owner = THIS_MODULE,
DRM_FB_HELPER_DEFAULT_OPS,
.fb_setcolreg = psbfb_setcolreg,
.fb_read = drm_fb_helper_cfb_read,
.fb_write = drm_fb_helper_cfb_write,
.fb_fillrect = drm_fb_helper_cfb_fillrect,
.fb_copyarea = drm_fb_helper_cfb_copyarea,
.fb_imageblit = drm_fb_helper_cfb_imageblit,
.fb_mmap = psbfb_mmap,
};
/**
* psb_framebuffer_init - initialize a framebuffer
* @dev: our DRM device
@ -207,11 +67,9 @@ static int psb_framebuffer_init(struct drm_device *dev,
*
* TODO: review object references
*/
static struct drm_framebuffer *psb_framebuffer_create
(struct drm_device *dev,
const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object *obj)
struct drm_framebuffer *psb_framebuffer_create(struct drm_device *dev,
const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object *obj)
{
struct drm_framebuffer *fb;
int ret;
@ -228,93 +86,6 @@ static struct drm_framebuffer *psb_framebuffer_create
return fb;
}
/**
* psbfb_create - create a framebuffer
* @fb_helper: the framebuffer helper
* @sizes: specification of the layout
*
* Create a framebuffer to the specifications provided
*/
static int psbfb_create(struct drm_fb_helper *fb_helper,
struct drm_fb_helper_surface_size *sizes)
{
struct drm_device *dev = fb_helper->dev;
struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct pci_dev *pdev = to_pci_dev(dev->dev);
struct fb_info *info;
struct drm_framebuffer *fb;
struct drm_mode_fb_cmd2 mode_cmd;
int size;
int ret;
struct psb_gem_object *backing;
struct drm_gem_object *obj;
u32 bpp, depth;
mode_cmd.width = sizes->surface_width;
mode_cmd.height = sizes->surface_height;
bpp = sizes->surface_bpp;
depth = sizes->surface_depth;
/* No 24bit packed */
if (bpp == 24)
bpp = 32;
mode_cmd.pitches[0] = ALIGN(mode_cmd.width * DIV_ROUND_UP(bpp, 8), 64);
size = mode_cmd.pitches[0] * mode_cmd.height;
size = ALIGN(size, PAGE_SIZE);
/* Allocate the framebuffer in the GTT with stolen page backing */
backing = psb_gem_create(dev, size, "fb", true, PAGE_SIZE);
if (IS_ERR(backing))
return PTR_ERR(backing);
obj = &backing->base;
memset(dev_priv->vram_addr + backing->offset, 0, size);
info = drm_fb_helper_alloc_info(fb_helper);
if (IS_ERR(info)) {
ret = PTR_ERR(info);
goto err_drm_gem_object_put;
}
mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth);
fb = psb_framebuffer_create(dev, &mode_cmd, obj);
if (IS_ERR(fb)) {
ret = PTR_ERR(fb);
goto err_drm_gem_object_put;
}
fb_helper->fb = fb;
info->fbops = &psbfb_unaccel_ops;
info->fix.smem_start = dev_priv->fb_base;
info->fix.smem_len = size;
info->fix.ywrapstep = 0;
info->fix.ypanstep = 0;
/* Accessed stolen memory directly */
info->screen_base = dev_priv->vram_addr + backing->offset;
info->screen_size = size;
drm_fb_helper_fill_info(info, fb_helper, sizes);
info->fix.mmio_start = pci_resource_start(pdev, 0);
info->fix.mmio_len = pci_resource_len(pdev, 0);
/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
dev_dbg(dev->dev, "allocated %dx%d fb\n", fb->width, fb->height);
return 0;
err_drm_gem_object_put:
drm_gem_object_put(obj);
return ret;
}
/**
* psb_user_framebuffer_create - create framebuffer
* @dev: our DRM device
@ -346,108 +117,8 @@ static struct drm_framebuffer *psb_user_framebuffer_create
return fb;
}
static int psbfb_probe(struct drm_fb_helper *fb_helper,
struct drm_fb_helper_surface_size *sizes)
{
struct drm_device *dev = fb_helper->dev;
struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
unsigned int fb_size;
int bytespp;
bytespp = sizes->surface_bpp / 8;
if (bytespp == 3) /* no 24bit packed */
bytespp = 4;
/* If the mode will not fit in 32bit then switch to 16bit to get
a console on full resolution. The X mode setting server will
allocate its own 32bit GEM framebuffer */
fb_size = ALIGN(sizes->surface_width * bytespp, 64) *
sizes->surface_height;
fb_size = ALIGN(fb_size, PAGE_SIZE);
if (fb_size > dev_priv->vram_stolen_size) {
sizes->surface_bpp = 16;
sizes->surface_depth = 16;
}
return psbfb_create(fb_helper, sizes);
}
static const struct drm_fb_helper_funcs psb_fb_helper_funcs = {
.fb_probe = psbfb_probe,
};
static int psb_fbdev_destroy(struct drm_device *dev,
struct drm_fb_helper *fb_helper)
{
struct drm_framebuffer *fb = fb_helper->fb;
drm_fb_helper_unregister_info(fb_helper);
drm_fb_helper_fini(fb_helper);
drm_framebuffer_unregister_private(fb);
drm_framebuffer_cleanup(fb);
if (fb->obj[0])
drm_gem_object_put(fb->obj[0]);
kfree(fb);
return 0;
}
int psb_fbdev_init(struct drm_device *dev)
{
struct drm_fb_helper *fb_helper;
struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
int ret;
fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL);
if (!fb_helper) {
dev_err(dev->dev, "no memory\n");
return -ENOMEM;
}
dev_priv->fb_helper = fb_helper;
drm_fb_helper_prepare(dev, fb_helper, 32, &psb_fb_helper_funcs);
ret = drm_fb_helper_init(dev, fb_helper);
if (ret)
goto free;
/* disable all the possible outputs/crtcs before entering KMS mode */
drm_helper_disable_unused_functions(dev);
ret = drm_fb_helper_initial_config(fb_helper);
if (ret)
goto fini;
return 0;
fini:
drm_fb_helper_fini(fb_helper);
free:
drm_fb_helper_unprepare(fb_helper);
kfree(fb_helper);
return ret;
}
static void psb_fbdev_fini(struct drm_device *dev)
{
struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
if (!dev_priv->fb_helper)
return;
psb_fbdev_destroy(dev, dev_priv->fb_helper);
drm_fb_helper_unprepare(dev_priv->fb_helper);
kfree(dev_priv->fb_helper);
dev_priv->fb_helper = NULL;
}
static const struct drm_mode_config_funcs psb_mode_funcs = {
.fb_create = psb_user_framebuffer_create,
.output_poll_changed = drm_fb_helper_output_poll_changed,
};
static void psb_setup_outputs(struct drm_device *dev)
@ -515,7 +186,6 @@ void psb_modeset_init(struct drm_device *dev)
{
struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
struct pci_dev *pdev = to_pci_dev(dev->dev);
int i;
if (drmm_mode_config_init(dev))
@ -526,10 +196,6 @@ void psb_modeset_init(struct drm_device *dev)
dev->mode_config.funcs = &psb_mode_funcs;
/* set memory base */
/* Oaktrail and Poulsbo should use BAR 2*/
pci_read_config_dword(pdev, PSB_BSM, (u32 *)&(dev_priv->fb_base));
/* num pipes is 2 for PSB but 1 for Mrst */
for (i = 0; i < dev_priv->num_pipe; i++)
psb_intel_crtc_init(dev, i, mode_dev);
@ -550,6 +216,5 @@ void psb_modeset_cleanup(struct drm_device *dev)
struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
if (dev_priv->modeset) {
drm_kms_helper_poll_fini(dev);
psb_fbdev_fini(dev);
}
}

View File

@ -21,7 +21,6 @@
#include <drm/drm.h>
#include <drm/drm_aperture.h>
#include <drm/drm_drv.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_file.h>
#include <drm/drm_ioctl.h>
#include <drm/drm_pciids.h>
@ -387,7 +386,6 @@ static int psb_driver_load(struct drm_device *dev, unsigned long flags)
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
psb_modeset_init(dev);
psb_fbdev_init(dev);
drm_kms_helper_poll_init(dev);
/* Only add backlight support if we have LVDS or MIPI output */
@ -452,6 +450,8 @@ static int psb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ret)
return ret;
psb_fbdev_setup(dev_priv);
return 0;
}
@ -477,7 +477,6 @@ static const struct file_operations psb_gem_fops = {
static const struct drm_driver driver = {
.driver_features = DRIVER_MODESET | DRIVER_GEM,
.lastclose = drm_fb_helper_lastclose,
.num_ioctls = ARRAY_SIZE(psb_ioctls),

View File

@ -193,8 +193,6 @@
#define KSEL_BYPASS_25 6
#define KSEL_BYPASS_83_100 7
struct drm_fb_helper;
struct opregion_header;
struct opregion_acpi;
struct opregion_swsci;
@ -522,9 +520,6 @@ struct drm_psb_private {
uint32_t blc_adj1;
uint32_t blc_adj2;
struct drm_fb_helper *fb_helper;
resource_size_t fb_base;
bool dsr_enable;
u32 dsr_fb_update;
bool dpi_panel_on[3];
@ -610,7 +605,19 @@ extern void psb_lid_timer_takedown(struct drm_psb_private *dev_priv);
/* modesetting */
extern void psb_modeset_init(struct drm_device *dev);
extern void psb_modeset_cleanup(struct drm_device *dev);
extern int psb_fbdev_init(struct drm_device *dev);
/* framebuffer */
struct drm_framebuffer *psb_framebuffer_create(struct drm_device *dev,
const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object *obj);
/* fbdev */
#if defined(CONFIG_DRM_FBDEV_EMULATION)
void psb_fbdev_setup(struct drm_psb_private *dev_priv);
#else
static inline void psb_fbdev_setup(struct drm_psb_private *dev_priv)
{ }
#endif
/* backlight.c */
int gma_backlight_init(struct drm_device *dev);

View File

@ -32,17 +32,6 @@ static inline u32 gma_pipestat(int pipe)
BUG();
}
static inline u32 gma_pipe_event(int pipe)
{
if (pipe == 0)
return _PSB_PIPEA_EVENT_FLAG;
if (pipe == 1)
return _MDFLD_PIPEB_EVENT_FLAG;
if (pipe == 2)
return _MDFLD_PIPEC_EVENT_FLAG;
BUG();
}
static inline u32 gma_pipeconf(int pipe)
{
if (pipe == 0)

View File

@ -277,21 +277,13 @@ static int lima_gem_add_deps(struct drm_file *file, struct lima_submit *submit)
int i, err;
for (i = 0; i < ARRAY_SIZE(submit->in_sync); i++) {
struct dma_fence *fence = NULL;
if (!submit->in_sync[i])
continue;
err = drm_syncobj_find_fence(file, submit->in_sync[i],
0, 0, &fence);
err = drm_sched_job_add_syncobj_dependency(&submit->task->base, file,
submit->in_sync[i], 0);
if (err)
return err;
err = drm_sched_job_add_dependency(&submit->task->base, fence);
if (err) {
dma_fence_put(fence);
return err;
}
}
return 0;

View File

@ -667,6 +667,7 @@ static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master,
struct rockchip_hdmi *hdmi = dev_get_drvdata(dev);
dw_hdmi_unbind(hdmi->hdmi);
drm_encoder_cleanup(&hdmi->encoder.encoder);
clk_disable_unprepare(hdmi->ref_clk);
regulator_disable(hdmi->avdd_1v8);

View File

@ -2301,7 +2301,7 @@ static int vop2_create_crtcs(struct vop2 *vop2)
nvp = 0;
for (i = 0; i < vop2->registered_num_wins; i++) {
struct vop2_win *win = &vop2->win[i];
u32 possible_crtcs;
u32 possible_crtcs = 0;
if (vop2->data->soc_id == 3566) {
/*
@ -2327,12 +2327,11 @@ static int vop2_create_crtcs(struct vop2 *vop2)
/* change the unused primary window to overlay window */
win->type = DRM_PLANE_TYPE_OVERLAY;
}
} else if (win->type == DRM_PLANE_TYPE_OVERLAY) {
possible_crtcs = (1 << nvps) - 1;
} else {
possible_crtcs = 0;
}
if (win->type == DRM_PLANE_TYPE_OVERLAY)
possible_crtcs = (1 << nvps) - 1;
ret = vop2_plane_init(vop2, win, possible_crtcs);
if (ret) {
drm_err(vop2->drm, "failed to init plane %s: %d\n",
@ -2680,6 +2679,8 @@ static int vop2_bind(struct device *dev, struct device *master, void *data)
vop2->len = resource_size(res);
vop2->map = devm_regmap_init_mmio(dev, vop2->regs, &vop2_regmap_config);
if (IS_ERR(vop2->map))
return PTR_ERR(vop2->map);
ret = vop2_win_init(vop2);
if (ret)

View File

@ -67,6 +67,11 @@ struct convert_to_argb2101010_result {
const u32 expected[TEST_BUF_SIZE];
};
struct convert_to_mono_result {
unsigned int dst_pitch;
const u8 expected[TEST_BUF_SIZE];
};
struct convert_xrgb8888_case {
const char *name;
unsigned int pitch;
@ -82,6 +87,7 @@ struct convert_xrgb8888_case {
struct convert_to_argb8888_result argb8888_result;
struct convert_to_xrgb2101010_result xrgb2101010_result;
struct convert_to_argb2101010_result argb2101010_result;
struct convert_to_mono_result mono_result;
};
static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
@ -131,6 +137,10 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
.dst_pitch = 0,
.expected = { 0xFFF00000 },
},
.mono_result = {
.dst_pitch = 0,
.expected = { 0b0 },
},
},
{
.name = "single_pixel_clip_rectangle",
@ -181,6 +191,10 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
.dst_pitch = 0,
.expected = { 0xFFF00000 },
},
.mono_result = {
.dst_pitch = 0,
.expected = { 0b0 },
},
},
{
/* Well known colors: White, black, red, green, blue, magenta,
@ -293,6 +307,15 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
0xFFFFFC00, 0xC00FFFFF,
},
},
.mono_result = {
.dst_pitch = 0,
.expected = {
0b01,
0b10,
0b00,
0b11,
},
},
},
{
/* Randomly picked colors. Full buffer within the clip area. */
@ -300,96 +323,104 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = {
.pitch = 3 * 4,
.clip = DRM_RECT_INIT(0, 0, 3, 3),
.xrgb8888 = {
0xA10E449C, 0xB1114D05, 0xC1A80303,
0xD16C7073, 0xA20E449C, 0xB2114D05,
0xC2A80303, 0xD26C7073, 0xA30E449C,
0xA10E449C, 0xB1114D05, 0xC1A8F303,
0xD16CF073, 0xA20E449C, 0xB2114D05,
0xC2A80303, 0xD26CF073, 0xA30E449C,
},
.gray8_result = {
.dst_pitch = 5,
.expected = {
0x3C, 0x33, 0x34, 0x00, 0x00,
0x6F, 0x3C, 0x33, 0x00, 0x00,
0x34, 0x6F, 0x3C, 0x00, 0x00,
0x3C, 0x33, 0xC4, 0x00, 0x00,
0xBB, 0x3C, 0x33, 0x00, 0x00,
0x34, 0xBB, 0x3C, 0x00, 0x00,
},
},
.rgb332_result = {
.dst_pitch = 5,
.expected = {
0x0A, 0x08, 0xA0, 0x00, 0x00,
0x6D, 0x0A, 0x08, 0x00, 0x00,
0xA0, 0x6D, 0x0A, 0x00, 0x00,
0x0A, 0x08, 0xBC, 0x00, 0x00,
0x7D, 0x0A, 0x08, 0x00, 0x00,
0xA0, 0x7D, 0x0A, 0x00, 0x00,
},
},
.rgb565_result = {
.dst_pitch = 10,
.expected = {
0x0A33, 0x1260, 0xA800, 0x0000, 0x0000,
0x6B8E, 0x0A33, 0x1260, 0x0000, 0x0000,
0xA800, 0x6B8E, 0x0A33, 0x0000, 0x0000,
0x0A33, 0x1260, 0xAF80, 0x0000, 0x0000,
0x6F8E, 0x0A33, 0x1260, 0x0000, 0x0000,
0xA800, 0x6F8E, 0x0A33, 0x0000, 0x0000,
},
.expected_swab = {
0x330A, 0x6012, 0x00A8, 0x0000, 0x0000,
0x8E6B, 0x330A, 0x6012, 0x0000, 0x0000,
0x00A8, 0x8E6B, 0x330A, 0x0000, 0x0000,
0x330A, 0x6012, 0x80AF, 0x0000, 0x0000,
0x8E6F, 0x330A, 0x6012, 0x0000, 0x0000,
0x00A8, 0x8E6F, 0x330A, 0x0000, 0x0000,
},
},
.xrgb1555_result = {
.dst_pitch = 10,
.expected = {
0x0513, 0x0920, 0x5400, 0x0000, 0x0000,
0x35CE, 0x0513, 0x0920, 0x0000, 0x0000,
0x5400, 0x35CE, 0x0513, 0x0000, 0x0000,
0x0513, 0x0920, 0x57C0, 0x0000, 0x0000,
0x37CE, 0x0513, 0x0920, 0x0000, 0x0000,
0x5400, 0x37CE, 0x0513, 0x0000, 0x0000,
},
},
.argb1555_result = {
.dst_pitch = 10,
.expected = {
0x8513, 0x8920, 0xD400, 0x0000, 0x0000,
0xB5CE, 0x8513, 0x8920, 0x0000, 0x0000,
0xD400, 0xB5CE, 0x8513, 0x0000, 0x0000,
0x8513, 0x8920, 0xD7C0, 0x0000, 0x0000,
0xB7CE, 0x8513, 0x8920, 0x0000, 0x0000,
0xD400, 0xB7CE, 0x8513, 0x0000, 0x0000,
},
},
.rgba5551_result = {
.dst_pitch = 10,
.expected = {
0x0A27, 0x1241, 0xA801, 0x0000, 0x0000,
0x6B9D, 0x0A27, 0x1241, 0x0000, 0x0000,
0xA801, 0x6B9D, 0x0A27, 0x0000, 0x0000,
0x0A27, 0x1241, 0xAF81, 0x0000, 0x0000,
0x6F9D, 0x0A27, 0x1241, 0x0000, 0x0000,
0xA801, 0x6F9D, 0x0A27, 0x0000, 0x0000,
},
},
.rgb888_result = {
.dst_pitch = 15,
.expected = {
0x9C, 0x44, 0x0E, 0x05, 0x4D, 0x11, 0x03, 0x03, 0xA8,
0x9C, 0x44, 0x0E, 0x05, 0x4D, 0x11, 0x03, 0xF3, 0xA8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x73, 0x70, 0x6C, 0x9C, 0x44, 0x0E, 0x05, 0x4D, 0x11,
0x73, 0xF0, 0x6C, 0x9C, 0x44, 0x0E, 0x05, 0x4D, 0x11,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x03, 0xA8, 0x73, 0x70, 0x6C, 0x9C, 0x44, 0x0E,
0x03, 0x03, 0xA8, 0x73, 0xF0, 0x6C, 0x9C, 0x44, 0x0E,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
},
.argb8888_result = {
.dst_pitch = 20,
.expected = {
0xFF0E449C, 0xFF114D05, 0xFFA80303, 0x00000000, 0x00000000,
0xFF6C7073, 0xFF0E449C, 0xFF114D05, 0x00000000, 0x00000000,
0xFFA80303, 0xFF6C7073, 0xFF0E449C, 0x00000000, 0x00000000,
0xFF0E449C, 0xFF114D05, 0xFFA8F303, 0x00000000, 0x00000000,
0xFF6CF073, 0xFF0E449C, 0xFF114D05, 0x00000000, 0x00000000,
0xFFA80303, 0xFF6CF073, 0xFF0E449C, 0x00000000, 0x00000000,
},
},
.xrgb2101010_result = {
.dst_pitch = 20,
.expected = {
0x03844672, 0x0444D414, 0x2A20300C, 0x00000000, 0x00000000,
0x1B1705CD, 0x03844672, 0x0444D414, 0x00000000, 0x00000000,
0x2A20300C, 0x1B1705CD, 0x03844672, 0x00000000, 0x00000000,
0x03844672, 0x0444D414, 0x2A2F3C0C, 0x00000000, 0x00000000,
0x1B1F0DCD, 0x03844672, 0x0444D414, 0x00000000, 0x00000000,
0x2A20300C, 0x1B1F0DCD, 0x03844672, 0x00000000, 0x00000000,
},
},
.argb2101010_result = {
.dst_pitch = 20,
.expected = {
0xC3844672, 0xC444D414, 0xEA20300C, 0x00000000, 0x00000000,
0xDB1705CD, 0xC3844672, 0xC444D414, 0x00000000, 0x00000000,
0xEA20300C, 0xDB1705CD, 0xC3844672, 0x00000000, 0x00000000,
0xC3844672, 0xC444D414, 0xEA2F3C0C, 0x00000000, 0x00000000,
0xDB1F0DCD, 0xC3844672, 0xC444D414, 0x00000000, 0x00000000,
0xEA20300C, 0xDB1F0DCD, 0xC3844672, 0x00000000, 0x00000000,
},
},
.mono_result = {
.dst_pitch = 2,
.expected = {
0b100, 0b000,
0b001, 0b000,
0b010, 0b000,
},
},
},
@ -409,15 +440,12 @@ static size_t conversion_buf_size(u32 dst_format, unsigned int dst_pitch,
const struct drm_rect *clip)
{
const struct drm_format_info *dst_fi = drm_format_info(dst_format);
unsigned int bpp;
if (!dst_fi)
return -EINVAL;
if (!dst_pitch) {
bpp = drm_format_info_bpp(dst_fi, 0);
dst_pitch = DIV_ROUND_UP(drm_rect_width(clip) * bpp, 8);
}
if (!dst_pitch)
dst_pitch = drm_format_info_min_pitch(dst_fi, 0, drm_rect_width(clip));
return dst_pitch * drm_rect_height(clip);
}
@ -792,6 +820,36 @@ static void drm_test_fb_xrgb8888_to_argb2101010(struct kunit *test)
KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
}
static void drm_test_fb_xrgb8888_to_mono(struct kunit *test)
{
const struct convert_xrgb8888_case *params = test->param_value;
const struct convert_to_mono_result *result = &params->mono_result;
size_t dst_size;
u8 *buf = NULL;
__le32 *xrgb8888 = NULL;
struct iosys_map dst, src;
struct drm_framebuffer fb = {
.format = drm_format_info(DRM_FORMAT_XRGB8888),
.pitches = { params->pitch, 0, 0 },
};
dst_size = conversion_buf_size(DRM_FORMAT_C1, result->dst_pitch, &params->clip);
KUNIT_ASSERT_GT(test, dst_size, 0);
buf = kunit_kzalloc(test, dst_size, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf);
iosys_map_set_vaddr(&dst, buf);
xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888);
iosys_map_set_vaddr(&src, xrgb8888);
drm_fb_xrgb8888_to_mono(&dst, &result->dst_pitch, &src, &fb, &params->clip);
KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
}
static struct kunit_case drm_format_helper_test_cases[] = {
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_gray8, convert_xrgb8888_gen_params),
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb332, convert_xrgb8888_gen_params),
@ -803,6 +861,7 @@ static struct kunit_case drm_format_helper_test_cases[] = {
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_argb8888, convert_xrgb8888_gen_params),
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_xrgb2101010, convert_xrgb8888_gen_params),
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_argb2101010, convert_xrgb8888_gen_params),
KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_mono, convert_xrgb8888_gen_params),
{}
};

View File

@ -545,7 +545,6 @@ static int bochs_kms_init(struct bochs_device *bochs)
bochs->dev->mode_config.preferred_depth = 24;
bochs->dev->mode_config.prefer_shadow = 0;
bochs->dev->mode_config.prefer_shadow_fbdev = 1;
bochs->dev->mode_config.quirk_addfb_prefer_host_byte_order = true;
bochs->dev->mode_config.funcs = &bochs_mode_funcs;

View File

@ -84,6 +84,7 @@ EXPORT_SYMBOL(ttm_bo_move_to_lru_tail);
* ttm_bo_set_bulk_move - update BOs bulk move object
*
* @bo: The buffer object.
* @bulk: bulk move structure
*
* Update the BOs bulk move object, making sure that resources are added/removed
* as well. A bulk move allows to move many resource on the LRU at once,
@ -748,7 +749,7 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo,
*
* @bo: Pointer to a struct ttm_buffer_object. the data of which
* we want to allocate space for.
* @proposed_placement: Proposed new placement for the buffer object.
* @placement: Proposed new placement for the buffer object.
* @mem: A struct ttm_resource.
* @ctx: if and how to sleep, lock buffers and alloc memory
*

View File

@ -39,17 +39,6 @@ struct vgem_file {
struct mutex fence_mutex;
};
#define to_vgem_bo(x) container_of(x, struct drm_vgem_gem_object, base)
struct drm_vgem_gem_object {
struct drm_gem_object base;
struct page **pages;
unsigned int pages_pin_count;
struct mutex pages_lock;
struct sg_table *table;
};
int vgem_fence_open(struct vgem_file *file);
int vgem_fence_attach_ioctl(struct drm_device *dev,
void *data,

View File

@ -2112,7 +2112,6 @@ int vmw_kms_init(struct vmw_private *dev_priv)
dev->mode_config.max_width = dev_priv->texture_max_width;
dev->mode_config.max_height = dev_priv->texture_max_height;
dev->mode_config.preferred_depth = dev_priv->assume_16bpp ? 16 : 32;
dev->mode_config.prefer_shadow_fbdev = !dev_priv->has_mob;
drm_mode_create_suggested_offset_properties(dev);
vmw_kms_create_hotplug_mode_update_property(dev_priv);

View File

@ -584,8 +584,6 @@ static inline bool drm_drv_uses_atomic_modeset(struct drm_device *dev)
}
int drm_dev_set_unique(struct drm_device *dev, const char *name);
/* TODO: Inline drm_firmware_drivers_only() in all its callers. */
static inline bool drm_firmware_drivers_only(void)
{

View File

@ -195,15 +195,6 @@ struct drm_fb_helper {
*/
int preferred_bpp;
/**
* @hint_leak_smem_start:
*
* Hint to the fbdev emulation to store the framebuffer's physical
* address in struct &fb_info.fix.smem_start. If the hint is unset,
* the smem_start field should always be cleared to zero.
*/
bool hint_leak_smem_start;
#ifdef CONFIG_FB_DEFERRED_IO
/**
* @fbdefio:
@ -256,6 +247,7 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper);
struct fb_info *drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper);
void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper);
void drm_fb_helper_unregister_info(struct drm_fb_helper *fb_helper);
void drm_fb_helper_fill_info(struct fb_info *info,
struct drm_fb_helper *fb_helper,
@ -365,6 +357,10 @@ drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper)
return NULL;
}
static inline void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper)
{
}
static inline void drm_fb_helper_unregister_info(struct drm_fb_helper *fb_helper)
{
}

View File

@ -890,13 +890,6 @@ struct drm_mode_config {
/* dumb ioctl parameters */
uint32_t preferred_depth, prefer_shadow;
/**
* @prefer_shadow_fbdev:
*
* Hint to framebuffer emulation to prefer shadow-fb rendering.
*/
bool prefer_shadow_fbdev;
/**
* @quirk_addfb_prefer_xbgr_30bpp:
*