diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-04-17 02:43:32 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2011-04-28 00:56:23 -0400 |
commit | 1794d257fa7bab3ea5162f8abdca749996b65343 (patch) | |
tree | ea8d035a218a0cb0ee83443b3c25bd8df25567e2 /drivers/gpu/drm/drm_modes.c | |
parent | bbb0aef5cfe95fe9b51a7eeba4a440b69037b01f (diff) |
drm: Export the command-line mode parser
In the absence of configuration data for providing the fixed mode for
a panel, I would like to be able to pass such modes along a separate
module paramenter. To do so, I then need to parse a modeline from a
string, which drm is already capable of. Export that capability to the
drivers.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/drm_modes.c')
-rw-r--r-- | drivers/gpu/drm/drm_modes.c | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 25bf87390f53..207b7ebf8150 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c | |||
@@ -974,3 +974,157 @@ void drm_mode_connector_list_update(struct drm_connector *connector) | |||
974 | } | 974 | } |
975 | } | 975 | } |
976 | EXPORT_SYMBOL(drm_mode_connector_list_update); | 976 | EXPORT_SYMBOL(drm_mode_connector_list_update); |
977 | |||
978 | /** | ||
979 | * drm_mode_parse_command_line_for_connector - parse command line for connector | ||
980 | * @mode_option - per connector mode option | ||
981 | * @connector - connector to parse line for | ||
982 | * | ||
983 | * This parses the connector specific then generic command lines for | ||
984 | * modes and options to configure the connector. | ||
985 | * | ||
986 | * This uses the same parameters as the fb modedb.c, except for extra | ||
987 | * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd] | ||
988 | * | ||
989 | * enable/enable Digital/disable bit at the end | ||
990 | */ | ||
991 | bool drm_mode_parse_command_line_for_connector(const char *mode_option, | ||
992 | struct drm_connector *connector, | ||
993 | struct drm_cmdline_mode *mode) | ||
994 | { | ||
995 | const char *name; | ||
996 | unsigned int namelen; | ||
997 | int res_specified = 0, bpp_specified = 0, refresh_specified = 0; | ||
998 | unsigned int xres = 0, yres = 0, bpp = 32, refresh = 0; | ||
999 | int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0; | ||
1000 | int i; | ||
1001 | enum drm_connector_force force = DRM_FORCE_UNSPECIFIED; | ||
1002 | |||
1003 | if (!mode_option) | ||
1004 | mode_option = fb_mode_option; | ||
1005 | |||
1006 | if (!mode_option) { | ||
1007 | mode->specified = false; | ||
1008 | return false; | ||
1009 | } | ||
1010 | |||
1011 | name = mode_option; | ||
1012 | namelen = strlen(name); | ||
1013 | for (i = namelen-1; i >= 0; i--) { | ||
1014 | switch (name[i]) { | ||
1015 | case '@': | ||
1016 | namelen = i; | ||
1017 | if (!refresh_specified && !bpp_specified && | ||
1018 | !yres_specified) { | ||
1019 | refresh = simple_strtol(&name[i+1], NULL, 10); | ||
1020 | refresh_specified = 1; | ||
1021 | if (cvt || rb) | ||
1022 | cvt = 0; | ||
1023 | } else | ||
1024 | goto done; | ||
1025 | break; | ||
1026 | case '-': | ||
1027 | namelen = i; | ||
1028 | if (!bpp_specified && !yres_specified) { | ||
1029 | bpp = simple_strtol(&name[i+1], NULL, 10); | ||
1030 | bpp_specified = 1; | ||
1031 | if (cvt || rb) | ||
1032 | cvt = 0; | ||
1033 | } else | ||
1034 | goto done; | ||
1035 | break; | ||
1036 | case 'x': | ||
1037 | if (!yres_specified) { | ||
1038 | yres = simple_strtol(&name[i+1], NULL, 10); | ||
1039 | yres_specified = 1; | ||
1040 | } else | ||
1041 | goto done; | ||
1042 | case '0' ... '9': | ||
1043 | break; | ||
1044 | case 'M': | ||
1045 | if (!yres_specified) | ||
1046 | cvt = 1; | ||
1047 | break; | ||
1048 | case 'R': | ||
1049 | if (cvt) | ||
1050 | rb = 1; | ||
1051 | break; | ||
1052 | case 'm': | ||
1053 | if (!cvt) | ||
1054 | margins = 1; | ||
1055 | break; | ||
1056 | case 'i': | ||
1057 | if (!cvt) | ||
1058 | interlace = 1; | ||
1059 | break; | ||
1060 | case 'e': | ||
1061 | force = DRM_FORCE_ON; | ||
1062 | break; | ||
1063 | case 'D': | ||
1064 | if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) && | ||
1065 | (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB)) | ||
1066 | force = DRM_FORCE_ON; | ||
1067 | else | ||
1068 | force = DRM_FORCE_ON_DIGITAL; | ||
1069 | break; | ||
1070 | case 'd': | ||
1071 | force = DRM_FORCE_OFF; | ||
1072 | break; | ||
1073 | default: | ||
1074 | goto done; | ||
1075 | } | ||
1076 | } | ||
1077 | if (i < 0 && yres_specified) { | ||
1078 | xres = simple_strtol(name, NULL, 10); | ||
1079 | res_specified = 1; | ||
1080 | } | ||
1081 | done: | ||
1082 | if (res_specified) { | ||
1083 | mode->specified = true; | ||
1084 | mode->xres = xres; | ||
1085 | mode->yres = yres; | ||
1086 | } | ||
1087 | |||
1088 | if (refresh_specified) { | ||
1089 | mode->refresh_specified = true; | ||
1090 | mode->refresh = refresh; | ||
1091 | } | ||
1092 | |||
1093 | if (bpp_specified) { | ||
1094 | mode->bpp_specified = true; | ||
1095 | mode->bpp = bpp; | ||
1096 | } | ||
1097 | mode->rb = rb ? true : false; | ||
1098 | mode->cvt = cvt ? true : false; | ||
1099 | mode->interlace = interlace ? true : false; | ||
1100 | mode->force = force; | ||
1101 | |||
1102 | return true; | ||
1103 | } | ||
1104 | EXPORT_SYMBOL(drm_mode_parse_command_line_for_connector); | ||
1105 | |||
1106 | struct drm_display_mode * | ||
1107 | drm_mode_create_from_cmdline_mode(struct drm_device *dev, | ||
1108 | struct drm_cmdline_mode *cmd) | ||
1109 | { | ||
1110 | struct drm_display_mode *mode; | ||
1111 | |||
1112 | if (cmd->cvt) | ||
1113 | mode = drm_cvt_mode(dev, | ||
1114 | cmd->xres, cmd->yres, | ||
1115 | cmd->refresh_specified ? cmd->refresh : 60, | ||
1116 | cmd->rb, cmd->interlace, | ||
1117 | cmd->margins); | ||
1118 | else | ||
1119 | mode = drm_gtf_mode(dev, | ||
1120 | cmd->xres, cmd->yres, | ||
1121 | cmd->refresh_specified ? cmd->refresh : 60, | ||
1122 | cmd->interlace, | ||
1123 | cmd->margins); | ||
1124 | if (!mode) | ||
1125 | return NULL; | ||
1126 | |||
1127 | drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); | ||
1128 | return mode; | ||
1129 | } | ||
1130 | EXPORT_SYMBOL(drm_mode_create_from_cmdline_mode); | ||