display: DCI-P3 support in colorimetry
- Add COLORSPACE, SUPPORTED_COLORSPACES properties.
- SUPPORTED_COLORSPACES: each bit specifies supported colorspace.
- COLORSPACE: set one of the colorspace based on the input content.
- Populate DCIP3, DISPLAY_BT2020 color modes based on supported
color spaces.
- For P3 color gamut, set blend space as dcip3 srgb.
- For Bt2020 color gamut set Bt2020_srgb irresepctive of gamma transfer.
- If external DP supports colorspace, based on input layers, set
colorspace on DP.
CRs-Fixed: 2450712
Change-Id: I704003bd23df29e462189d4316cb935f8cdebf05
diff --git a/libdrmutils/drm_interface.h b/libdrmutils/drm_interface.h
index bebc23a..40999e0 100644
--- a/libdrmutils/drm_interface.h
+++ b/libdrmutils/drm_interface.h
@@ -396,6 +396,12 @@
* uint32_t - Frame trigger mode
*/
CONNECTOR_SET_FRAME_TRIGGER,
+ /*
+ * Op: Sets colorspace on DP connector
+ * Arg: uint32_t - Connector ID
+ * uint32_t - colorspace value bit-mask
+ */
+ CONNECTOR_SET_COLORSPACE,
};
enum struct DRMRotation {
@@ -620,6 +626,7 @@
uint32_t topology_control;
bool dyn_bitclk_support;
std::vector<uint8_t> edid;
+ uint32_t supported_colorspaces;
};
// All DRM Connectors as map<Connector_id , connector_info>
@@ -835,6 +842,23 @@
FRAME_DONE_WAIT_POSTED_START,
};
+/* DRM Color spaces exposed by the DP connector */
+enum struct DRMColorspace {
+ DEFAULT = 0,
+ SMPTE_170M_YCC,
+ BT709_YCC,
+ XVYCC_601,
+ XVYCC_709,
+ SYCC_601,
+ OPYCC_601,
+ OPRGB,
+ BT2020_CYCC,
+ BT2020_RGB,
+ BT2020_YCC,
+ DCI_P3_RGB_D65,
+ DCI_P3_RGB_THEATER,
+};
+
/* DRM Atomic Request Property Set.
*
* Helper class to create and populate atomic properties of DRM components
diff --git a/sde-drm/drm_atomic_req.cpp b/sde-drm/drm_atomic_req.cpp
index b565603..f3caca7 100644
--- a/sde-drm/drm_atomic_req.cpp
+++ b/sde-drm/drm_atomic_req.cpp
@@ -121,7 +121,8 @@
case DRMOps::CONNECTOR_SET_HDR_METADATA:
case DRMOps::CONNECTOR_SET_QSYNC_MODE:
case DRMOps::CONNECTOR_SET_TOPOLOGY_CONTROL:
- case DRMOps::CONNECTOR_SET_FRAME_TRIGGER: {
+ case DRMOps::CONNECTOR_SET_FRAME_TRIGGER:
+ case DRMOps::CONNECTOR_SET_COLORSPACE: {
drm_mgr_->GetConnectorMgr()->Perform(opcode, obj_id, drm_atomic_req_, args);
} break;
case DRMOps::DPPS_CACHE_FEATURE: {
diff --git a/sde-drm/drm_connector.cpp b/sde-drm/drm_connector.cpp
index 6eab006..6a5f10c 100644
--- a/sde-drm/drm_connector.cpp
+++ b/sde-drm/drm_connector.cpp
@@ -77,6 +77,20 @@
static uint8_t FRAME_TRIGGER_SERIALIZE = 1;
static uint8_t FRAME_TRIGGER_POSTED_START = 2;
+static uint8_t DRM_MODE_COLORIMETRY_DEFAULT = 0;
+static uint8_t DRM_MODE_COLORIMETRY_SMPTE_170M_YCC = 1;
+static uint8_t DRM_MODE_COLORIMETRY_BT709_YCC = 2;
+static uint8_t DRM_MODE_COLORIMETRY_XVYCC_601 = 3;
+static uint8_t DRM_MODE_COLORIMETRY_XVYCC_709 = 4;
+static uint8_t DRM_MODE_COLORIMETRY_SYCC_601 = 5;
+static uint8_t DRM_MODE_COLORIMETRY_OPYCC_601 = 6;
+static uint8_t DRM_MODE_COLORIMETRY_OPRGB = 7;
+static uint8_t DRM_MODE_COLORIMETRY_BT2020_CYCC = 8;
+static uint8_t DRM_MODE_COLORIMETRY_BT2020_RGB = 9;
+static uint8_t DRM_MODE_COLORIMETRY_BT2020_YCC = 10;
+static uint8_t DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65 = 11;
+static uint8_t DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER = 12;
+
static void PopulatePowerModes(drmModePropertyRes *prop) {
for (auto i = 0; i < prop->count_enums; i++) {
string enum_name(prop->enums[i].name);
@@ -103,6 +117,39 @@
}
}
+static void PopulateSupportedColorspaces(drmModePropertyRes *prop) {
+ for (auto i = 0; i < prop->count_enums; i++) {
+ string enum_name(prop->enums[i].name);
+ if (enum_name == "Default") {
+ DRM_MODE_COLORIMETRY_DEFAULT = prop->enums[i].value;
+ } else if (enum_name == "SMPTE_170M_YCC") {
+ DRM_MODE_COLORIMETRY_SMPTE_170M_YCC = prop->enums[i].value;
+ } else if (enum_name == "BT709_YCC") {
+ DRM_MODE_COLORIMETRY_BT709_YCC = prop->enums[i].value;
+ } else if (enum_name == "XVYCC_601") {
+ DRM_MODE_COLORIMETRY_XVYCC_601 = prop->enums[i].value;
+ } else if (enum_name == "XVYCC_709") {
+ DRM_MODE_COLORIMETRY_XVYCC_709 = prop->enums[i].value;
+ } else if (enum_name == "SYCC_601") {
+ DRM_MODE_COLORIMETRY_SYCC_601 = prop->enums[i].value;
+ } else if (enum_name == "opYCC_601") {
+ DRM_MODE_COLORIMETRY_OPYCC_601 = prop->enums[i].value;
+ } else if (enum_name == "opRGB") {
+ DRM_MODE_COLORIMETRY_OPRGB = prop->enums[i].value;
+ } else if (enum_name == "BT2020_CYCC") {
+ DRM_MODE_COLORIMETRY_BT2020_CYCC = prop->enums[i].value;
+ } else if (enum_name == "BT2020_RGB") {
+ DRM_MODE_COLORIMETRY_BT2020_RGB = prop->enums[i].value;
+ } else if (enum_name == "BT2020_YCC") {
+ DRM_MODE_COLORIMETRY_BT2020_YCC = prop->enums[i].value;
+ } else if (enum_name == "DCI_P3_RGB_D65") {
+ DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65 = prop->enums[i].value;
+ } else if (enum_name == "DCI_P3_RGB_Theater") {
+ DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER = prop->enums[i].value;
+ }
+ }
+}
+
static DRMTopology GetTopologyEnum(const string &topology) {
if (topology == "sde_singlepipe") return DRMTopology::SINGLE_LM;
if (topology == "sde_singlepipe_dsc") return DRMTopology::SINGLE_LM_DSC;
@@ -139,6 +186,55 @@
}
}
+static int32_t GetColorspace(DRMColorspace drm_colorspace) {
+ uint32_t colorspace = 0;
+ switch (drm_colorspace) {
+ case (DRMColorspace::DEFAULT):
+ colorspace = DRM_MODE_COLORIMETRY_DEFAULT;
+ break;
+ case (DRMColorspace::SMPTE_170M_YCC):
+ colorspace = DRM_MODE_COLORIMETRY_SMPTE_170M_YCC;
+ break;
+ case (DRMColorspace::BT709_YCC):
+ colorspace = DRM_MODE_COLORIMETRY_BT709_YCC;
+ break;
+ case (DRMColorspace::XVYCC_601):
+ colorspace = DRM_MODE_COLORIMETRY_XVYCC_601;
+ break;
+ case (DRMColorspace::XVYCC_709):
+ colorspace = DRM_MODE_COLORIMETRY_XVYCC_709;
+ break;
+ case (DRMColorspace::SYCC_601):
+ colorspace = DRM_MODE_COLORIMETRY_SYCC_601;
+ break;
+ case (DRMColorspace::OPYCC_601):
+ colorspace = DRM_MODE_COLORIMETRY_OPYCC_601;
+ break;
+ case (DRMColorspace::OPRGB):
+ colorspace = DRM_MODE_COLORIMETRY_OPRGB;
+ break;
+ case (DRMColorspace::BT2020_CYCC):
+ colorspace = DRM_MODE_COLORIMETRY_BT2020_CYCC;
+ break;
+ case (DRMColorspace::BT2020_RGB):
+ colorspace = DRM_MODE_COLORIMETRY_BT2020_RGB;
+ break;
+ case (DRMColorspace::BT2020_YCC):
+ colorspace = DRM_MODE_COLORIMETRY_BT2020_YCC;
+ break;
+ case (DRMColorspace::DCI_P3_RGB_D65):
+ colorspace = DRM_MODE_COLORIMETRY_DCI_P3_RGB_D65;
+ break;
+ case (DRMColorspace::DCI_P3_RGB_THEATER):
+ colorspace = DRM_MODE_COLORIMETRY_DCI_P3_RGB_THEATER;
+ break;
+ default:
+ colorspace = -1;
+ break;
+ }
+ return colorspace;
+}
+
#define __CLASS__ "DRMConnectorManager"
void DRMConnectorManager::Init(drmModeRes *resource) {
@@ -371,6 +467,8 @@
PopulateQsyncModes(info);
} else if (prop_enum == DRMProperty::FRAME_TRIGGER) {
PopulateFrameTriggerModes(info);
+ } else if (prop_enum == DRMProperty::COLORSPACE) {
+ PopulateSupportedColorspaces(info);
}
prop_mgr_.SetPropertyId(prop_enum, info->prop_id);
@@ -538,20 +636,20 @@
struct drm_msm_ext_hdr_properties *hdr_cdata = (struct drm_msm_ext_hdr_properties*)(blob->data);
- if(hdr_cdata) {
- hdr_info->hdr_supported = hdr_cdata->hdr_supported;
- hdr_info->hdr_plus_supported = hdr_cdata->hdr_plus_supported;
- hdr_info->hdr_eotf = hdr_cdata->hdr_eotf;
- hdr_info->hdr_metadata_type_one = hdr_cdata->hdr_metadata_type_one;
- hdr_info->hdr_max_luminance = hdr_cdata->hdr_max_luminance;
- hdr_info->hdr_avg_luminance = hdr_cdata->hdr_avg_luminance;
- hdr_info->hdr_min_luminance = hdr_cdata->hdr_min_luminance;
- DRM_LOGI("hdr_supported = %d, hdr_plus_supported = %d, hdr_eotf = %d, "
- "hdr_metadata_type_one = %d, hdr_max_luminance = %d, hdr_avg_luminance = %d, "
- "hdr_min_luminance = %d\n", hdr_info->hdr_supported,
- hdr_info->hdr_plus_supported,
- hdr_info->hdr_eotf, hdr_info->hdr_metadata_type_one, hdr_info->hdr_max_luminance,
- hdr_info->hdr_avg_luminance, hdr_info->hdr_min_luminance);
+ if (hdr_cdata) {
+ hdr_info->hdr_supported = hdr_cdata->hdr_supported;
+ hdr_info->hdr_plus_supported = hdr_cdata->hdr_plus_supported;
+ hdr_info->hdr_eotf = hdr_cdata->hdr_eotf;
+ hdr_info->hdr_metadata_type_one = hdr_cdata->hdr_metadata_type_one;
+ hdr_info->hdr_max_luminance = hdr_cdata->hdr_max_luminance;
+ hdr_info->hdr_avg_luminance = hdr_cdata->hdr_avg_luminance;
+ hdr_info->hdr_min_luminance = hdr_cdata->hdr_min_luminance;
+ DRM_LOGI("hdr_supported = %d, hdr_plus_supported = %d, hdr_eotf = %d, "
+ "hdr_metadata_type_one = %d, hdr_max_luminance = %d, hdr_avg_luminance = %d, "
+ "hdr_min_luminance = %d\n", hdr_info->hdr_supported,
+ hdr_info->hdr_plus_supported,
+ hdr_info->hdr_eotf, hdr_info->hdr_metadata_type_one, hdr_info->hdr_max_luminance,
+ hdr_info->hdr_avg_luminance, hdr_info->hdr_min_luminance);
}
drmModeFreePropertyBlob(blob);
}
@@ -660,6 +758,13 @@
ParseCapabilities(props->prop_values[index], &info->edid);
}
+ if (prop_mgr_.IsPropertyAvailable(DRMProperty::SUPPORTED_COLORSPACES)) {
+ index = std::distance(props->props,
+ std::find(props->props, props->props + props->count_props,
+ prop_mgr_.GetPropertyId(DRMProperty::SUPPORTED_COLORSPACES)));
+ info->supported_colorspaces = props->prop_values[index];
+ }
+
drmModeFreeObjectProperties(props);
return 0;
@@ -819,6 +924,27 @@
}
} break;
+ case DRMOps::CONNECTOR_SET_COLORSPACE: {
+ if (!prop_mgr_.IsPropertyAvailable(DRMProperty::COLORSPACE)) {
+ return;
+ }
+ DRMColorspace drm_colorspace = static_cast<DRMColorspace>(va_arg(args, uint32_t));
+ int32_t colorspace = 0;
+ colorspace = GetColorspace(drm_colorspace);
+ if (colorspace >= 0) {
+ uint32_t prop_id = prop_mgr_.GetPropertyId(DRMProperty::COLORSPACE);
+ int ret = drmModeAtomicAddProperty(req, obj_id, prop_id, colorspace);
+ if (ret < 0) {
+ DRM_LOGE("AtomicAddProperty failed obj_id 0x%x, prop_id %d mode %d ret %d",
+ obj_id, prop_id, colorspace, ret);
+ } else {
+ DRM_LOGD("Connector %d: Setting colorspace %d", obj_id, colorspace);
+ }
+ } else {
+ DRM_LOGE("Invalid colorspace %d", colorspace);
+ }
+ } break;
+
default:
DRM_LOGE("Invalid opcode %d to set on connector %d", code, obj_id);
break;
diff --git a/sde-drm/drm_property.cpp b/sde-drm/drm_property.cpp
index 0269f89..c144aad 100644
--- a/sde-drm/drm_property.cpp
+++ b/sde-drm/drm_property.cpp
@@ -160,6 +160,8 @@
if (name == "SDE_VIG_1D_LUT_IGC_V6") { return DRMProperty::SDE_VIG_1D_LUT_IGC_V6; }
if (name == "SDE_VIG_3D_LUT_GAMUT_V6") { return DRMProperty::SDE_VIG_3D_LUT_GAMUT_V6; }
if (name == "frame_trigger_mode") { return DRMProperty::FRAME_TRIGGER; }
+ if (name == "Colorspace") { return DRMProperty::COLORSPACE; }
+ if (name == "supported_colorspaces") { return DRMProperty::SUPPORTED_COLORSPACES; }
return DRMProperty::INVALID;
}
diff --git a/sde-drm/drm_property.h b/sde-drm/drm_property.h
index 32fe817..dcda7aa 100644
--- a/sde-drm/drm_property.h
+++ b/sde-drm/drm_property.h
@@ -165,6 +165,8 @@
SDE_LTM_QUEUE_BUFFER3,
SDE_LTM_VLUT,
FRAME_TRIGGER,
+ COLORSPACE,
+ SUPPORTED_COLORSPACES,
// Insert above
MAX
diff --git a/sdm/include/private/hw_info_types.h b/sdm/include/private/hw_info_types.h
index 0f5f94c..d182269 100644
--- a/sdm/include/private/hw_info_types.h
+++ b/sdm/include/private/hw_info_types.h
@@ -152,6 +152,18 @@
kHdrEOTFHLG = 0x8,
};
+enum HwColorspace {
+ kColorspaceXvycc601 = (1 << 0),
+ kColorspaceXvycc709 = (1 << 1),
+ kColorspaceSycc601 = (1 << 2),
+ kColorspaceAdobeycc601 = (1 << 3),
+ kColorspaceAdobergb = (1 << 4),
+ kColorspaceBt2020cycc = (1 << 5),
+ kColorspaceBt2020ycc = (1 << 6),
+ kColorspaceBt2020rgb = (1 << 7),
+ kColorspaceDcip3 = (1 << 15)
+};
+
enum HWSrcTonemap {
kSrcTonemapNone,
kSrcTonemap1d, // DMA
@@ -373,6 +385,7 @@
bool qsync_support = false; // Specifies panel supports qsync feature or not.
bool dyn_bitclk_support = false; // Bit clk can be updated to avoid RF interference.
std::vector<uint64_t> bitclk_rates; // Supported bit clk levels.
+ uint32_t supported_colorspaces = 0; // supported_colorspaces for DP displays.
bool operator !=(const HWPanelInfo &panel_info) {
return ((port != panel_info.port) || (mode != panel_info.mode) ||
diff --git a/sdm/libs/core/display_pluggable.cpp b/sdm/libs/core/display_pluggable.cpp
index e34f155..820457f 100644
--- a/sdm/libs/core/display_pluggable.cpp
+++ b/sdm/libs/core/display_pluggable.cpp
@@ -269,7 +269,11 @@
DisplayError DisplayPluggable::InitializeColorModes() {
PrimariesTransfer pt = {};
- AttrVal var;
+ AttrVal var = {};
+ if (hw_panel_info_.supported_colorspaces) {
+ InitializeColorModesFromColorspace();
+ }
+
if (!hw_panel_info_.hdr_enabled) {
return kErrorNone;
} else {
@@ -284,16 +288,6 @@
color_modes_cs_.push_back(pt);
var.clear();
color_mode_attr_map_.insert(std::make_pair("hal_native", var));
-
- pt.primaries = ColorPrimaries_BT2020;
- pt.transfer = Transfer_sRGB;
- color_modes_cs_.push_back(pt);
- var.clear();
- var.push_back(std::make_pair(kColorGamutAttribute, kBt2020));
- var.push_back(std::make_pair(kGammaTransferAttribute, kSrgb));
- var.push_back(std::make_pair(kPictureQualityAttribute, kStandard));
- var.push_back(std::make_pair(kRenderIntentAttribute, "0"));
- color_mode_attr_map_.insert(std::make_pair(kDisplayBt2020, var));
}
var.clear();
@@ -319,6 +313,33 @@
return kErrorNone;
}
+void DisplayPluggable::InitializeColorModesFromColorspace() {
+ PrimariesTransfer pt = {};
+ AttrVal var = {};
+ if (hw_panel_info_.supported_colorspaces & kColorspaceDcip3) {
+ pt.primaries = ColorPrimaries_DCIP3;
+ pt.transfer = Transfer_sRGB;
+ var.clear();
+ var.push_back(std::make_pair(kColorGamutAttribute, kDcip3));
+ var.push_back(std::make_pair(kGammaTransferAttribute, kSrgb));
+ var.push_back(std::make_pair(kPictureQualityAttribute, kStandard));
+ var.push_back(std::make_pair(kRenderIntentAttribute, "0"));
+ color_modes_cs_.push_back(pt);
+ color_mode_attr_map_.insert(std::make_pair(kDisplayP3, var));
+ }
+ if (hw_panel_info_.supported_colorspaces & kColorspaceBt2020rgb) {
+ pt.primaries = ColorPrimaries_BT2020;
+ pt.transfer = Transfer_sRGB;
+ var.clear();
+ var.push_back(std::make_pair(kColorGamutAttribute, kBt2020));
+ var.push_back(std::make_pair(kGammaTransferAttribute, kSrgb));
+ var.push_back(std::make_pair(kPictureQualityAttribute, kStandard));
+ var.push_back(std::make_pair(kRenderIntentAttribute, "0"));
+ color_modes_cs_.push_back(pt);
+ color_mode_attr_map_.insert(std::make_pair(kDisplayBt2020, var));
+ }
+}
+
static PrimariesTransfer GetBlendSpaceFromAttributes(const std::string &color_gamut,
const std::string &transfer) {
PrimariesTransfer blend_space_ = {};
@@ -331,6 +352,9 @@
} else if (transfer == kGamma2_2) {
blend_space_.transfer = Transfer_Gamma2_2;
}
+ } else if (color_gamut == kDcip3) {
+ blend_space_.primaries = ColorPrimaries_DCIP3;
+ blend_space_.transfer = Transfer_sRGB;
} else if (color_gamut == kSrgb) {
blend_space_.primaries = ColorPrimaries_BT709_5;
blend_space_.transfer = Transfer_sRGB;
diff --git a/sdm/libs/core/display_pluggable.h b/sdm/libs/core/display_pluggable.h
index e61107b..2e7bd09 100644
--- a/sdm/libs/core/display_pluggable.h
+++ b/sdm/libs/core/display_pluggable.h
@@ -70,6 +70,7 @@
virtual void HwRecovery(const HWRecoveryEvent sdm_event_code);
void UpdateColorModes();
+ void InitializeColorModesFromColorspace();
private:
DisplayError GetOverrideConfig(uint32_t *mode_index);
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index ead4586..617145f 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -792,7 +792,7 @@
interface_str_ = "Virtual";
break;
case DRM_MODE_CONNECTOR_DisplayPort:
- // TODO(user): Add when available
+ hw_panel_info_.port = kPortDP;
interface_str_ = "DisplayPort";
break;
}
diff --git a/sdm/libs/core/drm/hw_tv_drm.cpp b/sdm/libs/core/drm/hw_tv_drm.cpp
index 4e76872..a1a2fff 100644
--- a/sdm/libs/core/drm/hw_tv_drm.cpp
+++ b/sdm/libs/core/drm/hw_tv_drm.cpp
@@ -70,6 +70,7 @@
using sde_drm::DRMOps;
using sde_drm::DRMTopology;
using sde_drm::DRMPowerMode;
+using sde_drm::DRMColorspace;
namespace sdm {
@@ -223,6 +224,7 @@
hw_panel_info_.hdr_plus_enabled = connector_info_.ext_hdr_prop.hdr_plus_supported;
hw_panel_info_.hdr_metadata_type_one = connector_info_.ext_hdr_prop.hdr_metadata_type_one;
hw_panel_info_.hdr_eotf = connector_info_.ext_hdr_prop.hdr_eotf;
+ hw_panel_info_.supported_colorspaces = connector_info_.supported_colorspaces;
// Convert the raw luminance values from driver to Candela per meter^2 unit.
float max_luminance = FLOAT(connector_info_.ext_hdr_prop.hdr_max_luminance);
@@ -279,6 +281,23 @@
const MasteringDisplay &mastering_display = layer_buffer->color_metadata.masteringDisplayInfo;
const ContentLightLevel &light_level = layer_buffer->color_metadata.contentLightLevel;
const Primaries &primaries = mastering_display.primaries;
+ // Set colorspace on external displays.
+ if (hw_panel_info_.port == kPortDP && hw_panel_info_.supported_colorspaces) {
+ LayerStack *stack = hw_layers->info.stack;
+ sde_drm::DRMColorspace colorspace = sde_drm::DRMColorspace::DEFAULT;
+ if (stack->blend_cs.primaries == ColorPrimaries_DCIP3 &&
+ stack->blend_cs.transfer == Transfer_sRGB) {
+ colorspace = sde_drm::DRMColorspace::DCI_P3_RGB_D65;
+ /* In case of BT2020_YCC, BT2020_RGB is not set based on the layer format. We set it based on
+ the final output of display port controller. Here even though the layer as YUV , it will be
+ color converted to RGB using SSPP and the format going out of DP will be RGB. Hence we
+ should set BT2020_RGB. */
+ } else if (stack->blend_cs.primaries == ColorPrimaries_BT2020) {
+ colorspace = sde_drm::DRMColorspace::BT2020_RGB;
+ }
+ DLOGV_IF(kTagDriverConfig, "Set colorspace = %d", colorspace);
+ drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_COLORSPACE, token_.conn_id, colorspace);
+ }
if (hdr_op == HWHDRLayerInfo::kSet && hdr_layer_info.hdr_layers.size() == 1) {
// Reset reset_hdr_flag_ to handle where there are two consecutive HDR video playbacks with not