hc
2023-11-06 e3e12f52b214121840b44c91de5b3e5af5d3eb84
kernel/drivers/gpu/drm/drm_edid.c
....@@ -4120,6 +4120,113 @@
41204120 hdmi->y420_cmdb_map = map;
41214121 }
41224122
4123
+#ifdef CONFIG_NO_GKI
4124
+static int drm_find_all_edid_extension(const struct edid *edid,
4125
+ int ext_id, int *ext_list)
4126
+{
4127
+ u8 *edid_ext = NULL;
4128
+ int i, count = 0;
4129
+
4130
+ /* No EDID or EDID extensions */
4131
+ if (edid == NULL || edid->extensions == 0)
4132
+ return -EINVAL;
4133
+
4134
+ /* too many EDID extensions */
4135
+ if (edid->extensions > 32)
4136
+ return -EINVAL;
4137
+
4138
+ /* Find CEA extension */
4139
+ for (i = 0; i < edid->extensions; i++) {
4140
+ edid_ext = (u8 *)edid + EDID_LENGTH * (i + 1);
4141
+ if (edid_ext[0] == ext_id) {
4142
+ *ext_list = i;
4143
+ ext_list++;
4144
+ count++;
4145
+ }
4146
+ }
4147
+
4148
+ return count;
4149
+}
4150
+
4151
+/*
4152
+ * Search EDID for CEA extension block.
4153
+ */
4154
+static u8 *drm_find_edid_extension_from_index(const struct edid *edid,
4155
+ int ext_id, int *ext_index)
4156
+{
4157
+ u8 *edid_ext = NULL;
4158
+ int i;
4159
+ /* No EDID or EDID extensions */
4160
+ if (edid == NULL || edid->extensions == 0)
4161
+ return NULL;
4162
+ /* Find CEA extension */
4163
+ for (i = *ext_index; i < edid->extensions; i++) {
4164
+ edid_ext = (u8 *)edid + EDID_LENGTH * (i + 1);
4165
+ if (edid_ext[0] == ext_id)
4166
+ break;
4167
+ }
4168
+ if (i >= edid->extensions)
4169
+ return NULL;
4170
+ *ext_index = i + 1;
4171
+ return edid_ext;
4172
+}
4173
+
4174
+static int
4175
+add_cea_modes(struct drm_connector *connector, struct edid *edid)
4176
+{
4177
+ const u8 *cea;
4178
+ const u8 *db, *hdmi = NULL, *video = NULL;
4179
+ u8 dbl, hdmi_len, video_len = 0;
4180
+ int i, count = 0, modes = 0;
4181
+ int ext_index = 0;
4182
+ int ext_list[32];
4183
+
4184
+ count = drm_find_all_edid_extension(edid, CEA_EXT, ext_list);
4185
+ for (i = 0; i < count; i++) {
4186
+ ext_index = ext_list[i];
4187
+ cea = drm_find_edid_extension_from_index(edid, CEA_EXT, &ext_index);
4188
+ if (cea && cea_revision(cea) >= 3) {
4189
+ int i, start, end;
4190
+
4191
+ if (cea_db_offsets(cea, &start, &end))
4192
+ return 0;
4193
+
4194
+ for_each_cea_db(cea, i, start, end) {
4195
+ db = &cea[i];
4196
+ dbl = cea_db_payload_len(db);
4197
+
4198
+ if (cea_db_tag(db) == VIDEO_BLOCK) {
4199
+ video = db + 1;
4200
+ video_len = dbl;
4201
+ modes += do_cea_modes(connector, video, dbl);
4202
+ } else if (cea_db_is_hdmi_vsdb(db)) {
4203
+ hdmi = db;
4204
+ hdmi_len = dbl;
4205
+ } else if (cea_db_is_y420vdb(db)) {
4206
+ const u8 *vdb420 = &db[2];
4207
+
4208
+ /* Add 4:2:0(only) modes present in EDID */
4209
+ modes += do_y420vdb_modes(connector,
4210
+ vdb420,
4211
+ dbl - 1);
4212
+ }
4213
+ }
4214
+ }
4215
+
4216
+ /*
4217
+ * We parse the HDMI VSDB after having added the cea modes as we will
4218
+ * be patching their flags when the sink supports stereo 3D.
4219
+ */
4220
+ if (hdmi)
4221
+ modes += do_hdmi_vsdb_modes(connector, hdmi, hdmi_len, video,
4222
+ video_len);
4223
+ }
4224
+
4225
+ return modes;
4226
+}
4227
+
4228
+#else
4229
+
41234230 static int
41244231 add_cea_modes(struct drm_connector *connector, struct edid *edid)
41254232 {
....@@ -4166,6 +4273,7 @@
41664273
41674274 return modes;
41684275 }
4276
+#endif
41694277
41704278 static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode)
41714279 {