Replace the combination of bpp and depth with a single color-mode
argument. Handle special cases in simpledrm and ofdrm. Hard-code
XRGB8888 as fallback format for cases where no given format works.

The color-mode argument accepts the same values as the kernel's video
parameter. These are mostly bpp values between 1 and 32. The exceptions
are 15, which has a color depth of 15 and a bpp value of 16; and 32,
which has a color depth of 24 and a bpp value of 32.

Signed-off-by: Thomas Zimmermann <tzimmerm...@suse.de>
---
 drivers/gpu/drm/drm_fb_helper.c     | 64 ++++++++++++++++-------------
 drivers/gpu/drm/drm_fbdev_generic.c |  5 ---
 drivers/gpu/drm/tiny/ofdrm.c        |  7 +++-
 drivers/gpu/drm/tiny/simpledrm.c    |  7 +++-
 4 files changed, 47 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 1369ca4ae39b..8dcbe3693fc0 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -1756,24 +1756,21 @@ static uint32_t drm_fb_helper_find_format(struct 
drm_fb_helper *fb_helper, const
        return DRM_FORMAT_INVALID;
 }
 
-static uint32_t drm_fb_helper_find_cmdline_format(struct drm_fb_helper 
*fb_helper,
-                                                 const uint32_t *formats, 
size_t format_count,
-                                                 const struct drm_cmdline_mode 
*cmdline_mode)
+static uint32_t drm_fb_helper_find_color_mode_format(struct drm_fb_helper 
*fb_helper,
+                                                    const uint32_t *formats, 
size_t format_count,
+                                                    unsigned int color_mode)
 {
        struct drm_device *dev = fb_helper->dev;
        uint32_t bpp, depth;
 
-       if (!cmdline_mode->bpp_specified)
-               return DRM_FORMAT_INVALID;
-
-       switch (cmdline_mode->bpp) {
+       switch (color_mode) {
        case 1:
        case 2:
        case 4:
        case 8:
        case 16:
        case 24:
-               bpp = depth = cmdline_mode->bpp;
+               bpp = depth = color_mode;
                break;
        case 15:
                bpp = 16;
@@ -1784,14 +1781,14 @@ static uint32_t 
drm_fb_helper_find_cmdline_format(struct drm_fb_helper *fb_helpe
                depth = 24;
                break;
        default:
-               drm_info(dev, "unsupported bpp value of %d\n", 
cmdline_mode->bpp);
+               drm_info(dev, "unsupported color mode of %d\n", color_mode);
                return DRM_FORMAT_INVALID;
        }
 
        return drm_fb_helper_find_format(fb_helper, formats, format_count, bpp, 
depth);
 }
 
-static int __drm_fb_helper_find_sizes(struct drm_fb_helper *fb_helper, int 
preferred_bpp,
+static int __drm_fb_helper_find_sizes(struct drm_fb_helper *fb_helper, 
unsigned int color_mode,
                                      struct drm_fb_helper_surface_size *sizes)
 {
        struct drm_client_dev *client = &fb_helper->client;
@@ -1817,10 +1814,10 @@ static int __drm_fb_helper_find_sizes(struct 
drm_fb_helper *fb_helper, int prefe
                drm_client_for_each_connector_iter(connector, &conn_iter) {
                        struct drm_cmdline_mode *cmdline_mode = 
&connector->cmdline_mode;
 
-                       surface_format = 
drm_fb_helper_find_cmdline_format(fb_helper,
-                                                                          
plane->format_types,
-                                                                          
plane->format_count,
-                                                                          
cmdline_mode);
+                       surface_format = 
drm_fb_helper_find_color_mode_format(fb_helper,
+                                                                             
plane->format_types,
+                                                                             
plane->format_count,
+                                                                             
cmdline_mode->bpp);
                        if (surface_format != DRM_FORMAT_INVALID)
                                break; /* found supported format */
                }
@@ -1829,17 +1826,23 @@ static int __drm_fb_helper_find_sizes(struct 
drm_fb_helper *fb_helper, int prefe
                if (surface_format != DRM_FORMAT_INVALID)
                        break; /* found supported format */
 
-               /* try preferred bpp/depth */
-               surface_format = drm_fb_helper_find_format(fb_helper, 
plane->format_types,
-                                                          plane->format_count, 
preferred_bpp,
-                                                          
dev->mode_config.preferred_depth);
+               /* try preferred color mode */
+               surface_format = drm_fb_helper_find_color_mode_format(fb_helper,
+                                                                     
plane->format_types,
+                                                                     
plane->format_count,
+                                                                     
color_mode);
                if (surface_format != DRM_FORMAT_INVALID)
                        break; /* found supported format */
        }
 
        if (surface_format == DRM_FORMAT_INVALID) {
+               /*
+                * If none of the given color modes works, fall back
+                * to XRGB8888. Drivers are expected to provide this
+                * format for compatibility with legacy applications.
+                */
                drm_warn(dev, "No compatible format found\n");
-               return -EAGAIN;
+               surface_format = DRM_FORMAT_XRGB8888;
        }
 
        info = drm_format_info(surface_format);
@@ -1899,7 +1902,7 @@ static int __drm_fb_helper_find_sizes(struct 
drm_fb_helper *fb_helper, int prefe
        return 0;
 }
 
-static int drm_fb_helper_find_sizes(struct drm_fb_helper *fb_helper, int 
preferred_bpp,
+static int drm_fb_helper_find_sizes(struct drm_fb_helper *fb_helper, unsigned 
int color_mode,
                                    struct drm_fb_helper_surface_size *sizes)
 {
        struct drm_client_dev *client = &fb_helper->client;
@@ -1908,7 +1911,7 @@ static int drm_fb_helper_find_sizes(struct drm_fb_helper 
*fb_helper, int preferr
        int ret;
 
        mutex_lock(&client->modeset_mutex);
-       ret = __drm_fb_helper_find_sizes(fb_helper, preferred_bpp, sizes);
+       ret = __drm_fb_helper_find_sizes(fb_helper, color_mode, sizes);
        mutex_unlock(&client->modeset_mutex);
 
        if (ret)
@@ -1931,13 +1934,13 @@ static int drm_fb_helper_find_sizes(struct 
drm_fb_helper *fb_helper, int preferr
  * the ->fb_probe callback.
  */
 static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
-                                        int preferred_bpp)
+                                        unsigned int color_mode)
 {
        struct drm_client_dev *client = &fb_helper->client;
        struct drm_fb_helper_surface_size sizes;
        int ret;
 
-       ret = drm_fb_helper_find_sizes(fb_helper, preferred_bpp, &sizes);
+       ret = drm_fb_helper_find_sizes(fb_helper, color_mode, &sizes);
        if (ret) {
                /* First time: disable all crtc's.. */
                if (!fb_helper->deferred_setup)
@@ -2116,7 +2119,7 @@ static void drm_setup_crtcs_fb(struct drm_fb_helper 
*fb_helper)
 /* Note: Drops fb_helper->lock before returning. */
 static int
 __drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper,
-                                         int bpp_sel)
+                                         unsigned int color_mode)
 {
        struct drm_device *dev = fb_helper->dev;
        struct fb_info *info;
@@ -2127,10 +2130,10 @@ __drm_fb_helper_initial_config_and_unlock(struct 
drm_fb_helper *fb_helper,
        height = dev->mode_config.max_height;
 
        drm_client_modeset_probe(&fb_helper->client, width, height);
-       ret = drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
+       ret = drm_fb_helper_single_fb_probe(fb_helper, color_mode);
        if (ret < 0) {
                if (ret == -EAGAIN) {
-                       fb_helper->preferred_bpp = bpp_sel;
+                       fb_helper->preferred_bpp = color_mode;
                        fb_helper->deferred_setup = true;
                        ret = 0;
                }
@@ -2176,7 +2179,7 @@ __drm_fb_helper_initial_config_and_unlock(struct 
drm_fb_helper *fb_helper,
 /**
  * drm_fb_helper_initial_config - setup a sane initial connector configuration
  * @fb_helper: fb_helper device struct
- * @bpp_sel: bpp value to use for the framebuffer configuration
+ * @color_mode: color mode to use for the framebuffer configuration
  *
  * Scans the CRTCs and connectors and tries to put together an initial setup.
  * At the moment, this is a cloned configuration across all heads with
@@ -2214,15 +2217,18 @@ __drm_fb_helper_initial_config_and_unlock(struct 
drm_fb_helper *fb_helper,
  * RETURNS:
  * Zero if everything went ok, nonzero otherwise.
  */
-int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel)
+int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int 
color_mode)
 {
        int ret;
 
        if (!drm_fbdev_emulation)
                return 0;
 
+       if (color_mode < 0)
+               return -EINVAL; // TODO: update function to use unsigned int
+
        mutex_lock(&fb_helper->lock);
-       ret = __drm_fb_helper_initial_config_and_unlock(fb_helper, bpp_sel);
+       ret = __drm_fb_helper_initial_config_and_unlock(fb_helper, color_mode);
 
        return ret;
 }
diff --git a/drivers/gpu/drm/drm_fbdev_generic.c 
b/drivers/gpu/drm/drm_fbdev_generic.c
index 0a4c160e0e58..db8c06402e47 100644
--- a/drivers/gpu/drm/drm_fbdev_generic.c
+++ b/drivers/gpu/drm/drm_fbdev_generic.c
@@ -478,11 +478,6 @@ void drm_fbdev_generic_setup(struct drm_device *dev,
         * will select XRGB8888 for the framebuffer formats. All drivers
         * have to support XRGB8888 for backwards compatibility with legacy
         * userspace, so it's the safe choice here.
-        *
-        * TODO: Replace struct drm_mode_config.preferred_depth and this
-        *       bpp value with a preferred format that is given as struct
-        *       drm_format_info. Then derive all other values from the
-        *       format.
         */
        if (!preferred_bpp)
                preferred_bpp = 32;
diff --git a/drivers/gpu/drm/tiny/ofdrm.c b/drivers/gpu/drm/tiny/ofdrm.c
index 39c5fd463fec..745a8b44517f 100644
--- a/drivers/gpu/drm/tiny/ofdrm.c
+++ b/drivers/gpu/drm/tiny/ofdrm.c
@@ -1352,6 +1352,7 @@ static int ofdrm_probe(struct platform_device *pdev)
 {
        struct ofdrm_device *odev;
        struct drm_device *dev;
+       unsigned int color_mode;
        int ret;
 
        odev = ofdrm_device_create(&ofdrm_driver, pdev);
@@ -1363,7 +1364,11 @@ static int ofdrm_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       drm_fbdev_generic_setup(dev, drm_format_info_bpp(odev->format, 0));
+       color_mode = drm_format_info_bpp(sdev->format, 0);
+       if (color_mode == 16)
+               color_mode = sdev->format->depth; // can be 15 or 16
+
+       drm_fbdev_generic_setup(dev, color_mode);
 
        return 0;
 }
diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c
index 7355617f38d3..f658b99c796a 100644
--- a/drivers/gpu/drm/tiny/simpledrm.c
+++ b/drivers/gpu/drm/tiny/simpledrm.c
@@ -802,6 +802,7 @@ static int simpledrm_probe(struct platform_device *pdev)
 {
        struct simpledrm_device *sdev;
        struct drm_device *dev;
+       unsigned int color_mode;
        int ret;
 
        sdev = simpledrm_device_create(&simpledrm_driver, pdev);
@@ -813,7 +814,11 @@ static int simpledrm_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       drm_fbdev_generic_setup(dev, drm_format_info_bpp(sdev->format, 0));
+       color_mode = drm_format_info_bpp(sdev->format, 0);
+       if (color_mode == 16)
+               color_mode = sdev->format->depth; // can be 15 or 16
+
+       drm_fbdev_generic_setup(dev, color_mode);
 
        return 0;
 }
-- 
2.39.0

Reply via email to